Initial commit.

This commit is contained in:
郑佩茹
2022-04-04 14:08:27 -06:00
parent 46dc4b2b3a
commit caac92e822
239 changed files with 71949 additions and 0 deletions

14
MogIt/Bindings.xml Normal file
View File

@@ -0,0 +1,14 @@
<Bindings>
<Binding name="MogIt" header="MogIt">
MogIt:ToggleFrame()
</Binding>
<Binding name="MogItPreview">
MogIt:TogglePreview()
</Binding>
<Binding name="MogIt_TooltipScrollUp" hidden="true">
MogIt.tooltip.model:SetFacing(MogIt.tooltip.model:GetFacing()+0.3);
</Binding>
<Binding name="MogIt_TooltipScrollDown" hidden="true">
MogIt.tooltip.model:SetFacing(MogIt.tooltip.model:GetFacing()-0.3);
</Binding>
</Bindings>

393
MogIt/Core/Core.lua Normal file
View File

@@ -0,0 +1,393 @@
local MogIt,mog = ...;
_G["MogIt"] = mog;
local L = mog.L;
local ItemInfo = LibStub("LibItemInfo-1.0");
LibStub("Libra"):EmbedWidgets(mog);
local character = DataStore_Containers and DataStore:GetCharacter();
mog.frame = CreateFrame("Frame","MogItFrame",UIParent,"ButtonFrameTemplate");
mog.list = {};
function mog:Error(msg)
DEFAULT_CHAT_FRAME:AddMessage("MogIt: "..msg,0.9,0.5,0.9);
end
--// Slash Commands
function mog:ToggleFrame()
ToggleFrame(mog.frame);
end
function mog:TogglePreview()
ToggleFrame(mog.view);
end
--//
--// Bindings
SLASH_MOGIT1 = "/mog";
SLASH_MOGIT2 = "/mogit";
SlashCmdList["MOGIT"] = mog.ToggleFrame;
BINDING_HEADER_MogIt = "MogIt";
BINDING_NAME_MogIt = L["Toggle Mogit"];
BINDING_NAME_MogItPreview = L["Toggle Preview"];
--//
--// LibDataBroker
mog.LDBI = LibStub("LibDBIcon-1.0");
mog.mmb = LibStub("LibDataBroker-1.1"):NewDataObject("MogIt",{
type = "launcher",
icon = "Interface\\Icons\\INV_Enchant_EssenceCosmicGreater",
OnClick = function(self,btn)
if btn == "RightButton" then
mog:TogglePreview();
else
mog:ToggleFrame();
end
end,
OnTooltipShow = function(self)
if not self or not self.AddLine then return end
self:AddLine("MogIt");
self:AddLine(L["Left click to toggle MogIt"],1,1,1);
self:AddLine(L["Right click to toggle the preview"],1,1,1);
end,
});
--//
--// Module API
mog.moduleVersion = 2;
mog.modules = {};
mog.moduleList = {};
function mog:GetModule(name)
return mog.modules[name];
end
function mog:GetActiveModule()
return mog.active;
end
function mog:RegisterModule(name,version,data)
if mog.modules[name] then
--mog:Error(L["The \124cFFFFFFFF%s\124r module is already loaded."]:format(name));
return mog.modules[name];
elseif type(version) ~= "number" or version < mog.moduleVersion then
mog:Error(L["The \124cFFFFFFFF%s\124r module needs to be updated to work with this version of MogIt."]:format(name));
return;
elseif version > mog.moduleVersion then
mog:Error(L["The \124cFFFFFFFF%s\124r module requires you to update MogIt for it to work."]:format(name));
return;
end
data = data or {};
data.name = name;
mog.modules[name] = data;
table.insert(mog.moduleList,data);
if mog.menu.active == mog.menu.modules then
mog.menu:Rebuild(1);
end
return data;
end
function mog:SetModule(module,text)
if mog.active and mog.active ~= module and mog.active.Unlist then
mog.active:Unlist(module);
end
mog.active = module;
mog:BuildList(true);
mog:FilterUpdate();
mog.frame.path:SetText(text or module.label or module.name or "");
end
function mog:BuildList(top,module)
if (module and mog.active and mog.active.name ~= module) then return end;
mog.list = mog.active and mog.active.BuildList and mog.active:BuildList() or {};
mog:SortList(nil,true);
mog.scroll:update(top and 1);
mog.filt.models:SetText(#mog.list);
end
--//
--// Item Cache
local itemCacheCallbacks = {
BuildList = mog.BuildList;
ModelOnEnter = function()
local owner = GameTooltip:GetOwner();
if owner and GameTooltip[mog] then
owner:OnEnter();
end
end,
ItemMenu = function()
mog.Item_Menu:Rebuild(1);
end,
SetMenu = function()
mog.Set_Menu:Rebuild(1);
end,
};
local pendingCallbacks = {};
for k in pairs(itemCacheCallbacks) do
pendingCallbacks[k] = {};
end
function mog:AddItemCacheCallback(name, func)
itemCacheCallbacks[name] = func;
pendingCallbacks[name] = {};
end
function mog:GetItemInfo(id, type)
if not type then return ItemInfo[id] end
if ItemInfo[id] then
-- clear pending items when they are cached
pendingCallbacks[type][id] = nil;
return ItemInfo[id];
elseif itemCacheCallbacks[type] then
-- add to pending items for this callback if not cached
pendingCallbacks[type][id] = true;
end
end
function mog.ItemInfoReceived()
for k, callback in pairs(pendingCallbacks) do
-- execute the callback if any items are pending for it
if next(callback) then
itemCacheCallbacks[k]();
end
end
end
ItemInfo.RegisterCallback(mog, "OnItemInfoReceivedBatch", "ItemInfoReceived");
--//
function mog:HasItem(itemID)
return TransmogTipList and tContains(TransmogTipList, itemID)
-- return GetItemCount(itemID, true) > 0 or (character and select(3, DataStore:GetContainerItemCount(character, itemID)) > 0)
end
--// Events
local defaults = {
profile = {
sortWishlist = false,
dressupPreview = false,
singlePreview = false,
previewUIPanel = false,
previewFixedSize = false,
noAnim = false,
minimap = {},
url = "Battle.net",
point = "CENTER",
gridWidth = 600,
gridHeight = 400,
rows = 2;
columns = 3,
gridDress = "preview",
sync = true,
previewProps = {
["*"] = {
w = 335,
h = 385,
point = "CENTER",
}
},
tooltip = true,
tooltipWidth = 300,
tooltipHeight = 300,
tooltipMouse = false,
tooltipDress = false,
tooltipRotate = true,
tooltipMog = true,
tooltipMod = "None",
tooltipCustomModel = false,
}
}
function mog.LoadSettings()
mog:UpdateGUI();
if mog.db.profile.minimap.hide then
mog.LDBI:Hide("MogIt");
else
mog.LDBI:Show("MogIt");
end
mog.tooltip:SetSize(mog.db.profile.tooltipWidth, mog.db.profile.tooltipHeight);
if mog.db.profile.tooltipRotate then mog.tooltip.rotate:Show() else mog.tooltip.rotate:Hide() end
mog.scroll:update();
mog:SetSinglePreview(mog.db.profile.singlePreview);
end
mog.frame:RegisterEvent("ADDON_LOADED");
mog.frame:RegisterEvent("PLAYER_LOGIN");
mog.frame:RegisterEvent("GET_ITEM_INFO_RECEIVED");
mog.frame:RegisterEvent("PLAYER_EQUIPMENT_CHANGED");
mog.frame:SetScript("OnEvent", function(self, event, ...)
return mog[event] and mog[event](mog, ...)
end);
function mog:ADDON_LOADED(addon)
if addon == MogIt then
local AceDB = LibStub("AceDB-3.0")
mog.db = AceDB:New("MogItDB", defaults, true)
mog.db.RegisterCallback(mog, "OnProfileChanged", "LoadSettings")
mog.db.RegisterCallback(mog, "OnProfileCopied", "LoadSettings")
mog.db.RegisterCallback(mog, "OnProfileReset", "LoadSettings")
if not mog.db.global.version then
end
mog.db.global.version = GetAddOnMetadata(MogIt,"Version");
mog.LDBI:Register("MogIt",mog.mmb,mog.db.profile.minimap);
for name,module in pairs(mog.moduleList) do
if module.MogItLoaded then
module:MogItLoaded()
end
end
elseif mog.modules[addon] then
mog.modules[addon].loaded = true;
if mog.menu.active == mog.menu.modules then
mog.menu:Rebuild(1)
end
end
end
function mog:PLAYER_LOGIN()
mog:LoadSettings()
self.frame:SetScript("OnSizeChanged", function(self, width, height)
mog.db.profile.gridWidth = width;
mog.db.profile.gridHeight = height;
mog:UpdateGUI(true);
end)
end
function mog:PLAYER_EQUIPMENT_CHANGED(slot, hasItem)
-- don't do anything if the slot is not visible (necklace, ring, trinket)
if mog.db.profile.gridDress == "equipped" then
for i, frame in ipairs(mog.models) do
local item = frame.data.item
if item then
local slotName = mog.mogSlots[slot];
if hasItem then
if (slot ~= INVSLOT_HEAD or ShowingHelm()) and (slot ~= INVSLOT_BACK or ShowingCloak()) then
frame:TryOn(mog.mogSlots[slot] and select(6, GetTransmogrifySlotInfo(slot)) or GetInventoryItemID("player", slot), slotName);
end
else
frame:UndressSlot(slot);
end
frame:TryOn(item);
end
end
end
end
--//
--// Data API
mog.data = {};
function mog:AddData(data,id,key,value)
if not data and id and key then return end;
if not mog.data[data] then
mog.data[data] = {};
end
if not mog.data[data][key] then
mog.data[data][key] = {};
end
mog.data[data][key][id] = value;
return value;
end
function mog:DeleteData(data,id,key)
if not mog.data[data] then return end;
if id and key then
mog.data[data][key][id] = nil;
elseif id then
for k,v in pairs(mog.data[data]) do
v[id] = nil;
end
elseif key then
mog.data[data][key] = nil;
else
mog.data[data] = nil;
end
end
function mog:GetData(data,id,key)
return mog.data[data] and mog.data[data][key] and mog.data[data][key][id];
end
--//
--// Slot Conversion
mog.slots = {
"HeadSlot",
"ShoulderSlot",
"BackSlot",
"ChestSlot",
"ShirtSlot",
"TabardSlot",
"WristSlot",
"HandsSlot",
"WaistSlot",
"LegsSlot",
"FeetSlot",
"MainHandSlot",
"SecondaryHandSlot",
};
mog.slotsType = {
INVTYPE_HEAD = "HeadSlot",
INVTYPE_SHOULDER = "ShoulderSlot",
INVTYPE_CLOAK = "BackSlot",
INVTYPE_CHEST = "ChestSlot",
INVTYPE_ROBE = "ChestSlot",
INVTYPE_BODY = "ShirtSlot",
INVTYPE_TABARD = "TabardSlot",
INVTYPE_WRIST = "WristSlot",
INVTYPE_HAND = "HandsSlot",
INVTYPE_WAIST = "WaistSlot",
INVTYPE_LEGS = "LegsSlot",
INVTYPE_FEET = "FeetSlot",
INVTYPE_2HWEAPON = "MainHandSlot",
INVTYPE_WEAPON = "MainHandSlot",
INVTYPE_WEAPONMAINHAND = "MainHandSlot",
INVTYPE_WEAPONOFFHAND = "SecondaryHandSlot",
INVTYPE_RANGED = "MainHandSlot",
INVTYPE_RANGEDRIGHT = "MainHandSlot",
INVTYPE_SHIELD = "SecondaryHandSlot",
INVTYPE_HOLDABLE = "SecondaryHandSlot",
INVTYPE_THROWN = "MainHandSlot"
};
-- all slot IDs that can be transmogrified
mog.mogSlots = {
[INVSLOT_HEAD] = "HeadSlot",
[INVSLOT_SHOULDER] = "ShoulderSlot",
[INVSLOT_BACK] = "BackSlot",
[INVSLOT_CHEST] = "ChestSlot",
[INVSLOT_BODY] = "ShirtSlot",
[INVSLOT_TABARD] = "TabardSlot",
[INVSLOT_WRIST] = "WristSlot",
[INVSLOT_HAND] = "HandsSlot",
[INVSLOT_WAIST] = "WaistSlot",
[INVSLOT_LEGS] = "LegsSlot",
[INVSLOT_FEET] = "FeetSlot",
[INVSLOT_MAINHAND] = "MainHandSlot",
[INVSLOT_OFFHAND] = "SecondaryHandSlot",
}
function mog:GetSlot(id)
return mog.slots[id] or mog.slotsType[id];
end
--//

432
MogIt/Core/Core.xml Normal file
View File

@@ -0,0 +1,432 @@
<?xml version="1.0" encoding="utf-8"?>
<Ui xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.blizzard.com/wow/ui/" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<!-- if find textures "Interface\FrameGeneral\_UI-Frame" and "Interface\FrameGeneral\UI-Frame"-->
<Texture name="_UI-Frame-TitleTileBg" file="Interface\AddOns\MogIt\FrameGeneral\_UI-Frame" virtual="true" horizTile="true" >
<Size x="256" y="17"/>
<TexCoords left="0.00000000" right="1.00000000" top="0.28906250" bottom="0.42187500"/>
</Texture>
<Texture name="UI-Frame-Portrait" file="Interface\AddOns\MogIt\FrameGeneral\UI-Frame" virtual="true">
<Size x="78" y="78"/>
<TexCoords left="0.00781250" right="0.61718750" top="0.00781250" bottom="0.61718750"/>
</Texture>
<Texture name="UI-Frame-TopCornerRight" file="Interface\AddOns\MogIt\FrameGeneral\UI-Frame" virtual="true">
<Size x="33" y="33"/>
<TexCoords left="0.63281250" right="0.89062500" top="0.00781250" bottom="0.26562500"/>
</Texture>
<Texture name="UI-Frame-TopLeftCorner" file="Interface\AddOns\MogIt\FrameGeneral\UI-Frame" virtual="true">
<Size x="32" y="32"/>
<TexCoords left="0.63281250" right="0.88281250" top="0.28125000" bottom="0.53125000"/>
</Texture>
<Texture name="_UI-Frame-TitleTile" file="Interface\AddOns\MogIt\FrameGeneral\_UI-Frame" virtual="true" horizTile="true" >
<Size x="256" y="28"/>
<TexCoords left="0.00000000" right="1.00000000" top="0.43750000" bottom="0.65625000"/>
</Texture>
<Texture name="_UI-Frame-TopTileStreaks" file="Interface\AddOns\MogIt\FrameGeneral\_UI-Frame" virtual="true" horizTile="true" >
<Size x="256" y="37"/>
<TexCoords left="0.00000000" right="1.00000000" top="0.67187500" bottom="0.96093750"/>
</Texture>
<Texture name="UI-Frame-BotCornerLeft" file="Interface\AddOns\MogIt\FrameGeneral\UI-Frame" virtual="true">
<Size x="14" y="14"/>
<TexCoords left="0.00781250" right="0.11718750" top="0.63281250" bottom="0.74218750"/>
</Texture>
<Texture name="UI-Frame-BotCornerRight" file="Interface\AddOns\MogIt\FrameGeneral\UI-Frame" virtual="true">
<Size x="11" y="11"/>
<TexCoords left="0.13281250" right="0.21875000" top="0.89843750" bottom="0.98437500"/>
</Texture>
<Texture name="_UI-Frame-Bot" file="Interface\AddOns\MogIt\FrameGeneral\_UI-Frame" virtual="true" horizTile="true" >
<Size x="256" y="9"/>
<TexCoords left="0.00000000" right="1.00000000" top="0.20312500" bottom="0.27343750"/>
</Texture>
<Texture name="!UI-Frame-LeftTile" file="Interface\AddOns\MogIt\FrameGeneral\!UI-Frame" virtual="true" vertTile="true" >
<Size x="16" y="256"/>
<TexCoords left="0.35937500" right="0.60937500" top="0.00000000" bottom="1.00000000"/>
</Texture>
<Texture name="!UI-Frame-RightTile" file="Interface\AddOns\MogIt\FrameGeneral\!UI-Frame" virtual="true" vertTile="true" >
<Size x="10" y="256"/>
<TexCoords left="0.17187500" right="0.32812500" top="0.00000000" bottom="1.00000000"/>
</Texture>
<Frame name="PortraitFrameTemplate" virtual="true">
<Size x="338" y="424"/>
<Layers>
<Layer level="BACKGROUND" textureSubLevel="-6">
<Texture name="$parentBg" file="Interface\AddOns\MogIt\FrameGeneral\UI-Background-Rock" horizTile="true" vertTile="true">
<Anchors>
<Anchor point="TOPLEFT" x="2" y="-21"/>
<Anchor point="BOTTOMRIGHT" x="-2" y="2"/>
</Anchors>
</Texture>
<Texture name="$parentTitleBg" inherits="_UI-Frame-TitleTileBG">
<Anchors>
<Anchor point="TOPLEFT" x="2" y="-3"/>
<Anchor point="TOPRIGHT" x="-25" y="-3"/>
</Anchors>
</Texture>
</Layer>
<Layer level="OVERLAY" textureSubLevel="-1">
<Texture name="$parentPortrait" parentKey="portrait">
<Size x="60" y="60"/>
<Anchors>
<Anchor point="TOPLEFT" x="-6" y="7" />
</Anchors>
</Texture>
</Layer>
<Layer level="OVERLAY">
<Texture name="$parentPortraitFrame" inherits="UI-Frame-Portrait" parentKey="portraitFrame">
<Anchors>
<Anchor point="TOPLEFT" x="-14" y="11"/>
</Anchors>
</Texture>
<Texture name="$parentTopRightCorner" inherits="UI-Frame-TopCornerRight">
<Anchors>
<Anchor point="TOPRIGHT" x="0" y="1"/>
</Anchors>
</Texture>
<Texture name="$parentTopLeftCorner" inherits="UI-Frame-TopLeftCorner" hidden="true" parentKey="topLeftCorner">
<Anchors>
<Anchor point="TOPLEFT" x="-6" y="1"/>
</Anchors>
</Texture>
<Texture name="$parentTopBorder" inherits="_UI-Frame-TitleTile" parentKey="topBorderBar">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentPortraitFrame" relativePoint="TOPRIGHT" x="0" y="-10" />
<Anchor point="TOPRIGHT" relativeTo="$parentTopRightCorner" relativePoint="TOPLEFT"/>
</Anchors>
</Texture>
<FontString name="$parentTitleText" inherits="GameFontNormal" text="" parentKey="TitleText">
<Anchors>
<Anchor point="TOP" x="0" y="-4"/>
<Anchor point="LEFT" x="60"/>
<Anchor point="RIGHT" x="-60"/>
</Anchors>
</FontString>
</Layer>
<Layer level="BORDER">
<Texture name="$parentTopTileStreaks" inherits="_UI-Frame-TopTileStreaks" parentKey="TopTileStreaks">
<Anchors>
<Anchor point="TOPLEFT" x="0" y="-21"/>
<Anchor point="TOPRIGHT" x="-2" y="-21"/>
</Anchors>
</Texture>
<Texture name="$parentBotLeftCorner" inherits="UI-Frame-BotCornerLeft">
<Anchors>
<Anchor point="BOTTOMLEFT" x="-6" y="-5"/>
</Anchors>
</Texture>
<Texture name="$parentBotRightCorner" inherits="UI-Frame-BotCornerRight">
<Anchors>
<Anchor point="BOTTOMRIGHT" x="0" y="-5"/>
</Anchors>
</Texture>
<Texture name="$parentBottomBorder" inherits="_UI-Frame-Bot">
<Anchors>
<Anchor point="BOTTOMLEFT" relativeTo="$parentBotLeftCorner" relativePoint="BOTTOMRIGHT" y="0"/>
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBotRightCorner" relativePoint="BOTTOMLEFT" y="0"/>
</Anchors>
</Texture>
<Texture name="$parentLeftBorder" inherits="!UI-Frame-LeftTile" parentKey="leftBorderBar">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentPortraitFrame" relativePoint="BOTTOMLEFT" x="8" y="0" />
<Anchor point="BOTTOMLEFT" relativeTo="$parentBotLeftCorner" relativePoint="TOPLEFT"/>
</Anchors>
</Texture>
<Texture name="$parentRightBorder" inherits="!UI-Frame-RightTile">
<Anchors>
<Anchor point="TOPRIGHT" relativeTo="$parentTopRightCorner" relativePoint="BOTTOMRIGHT" x="1"/>
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBotRightCorner" relativePoint="TOPRIGHT"/>
</Anchors>
</Texture>
</Layer>
</Layers>
<Frames>
<Button name="$parentCloseButton" inherits="UIPanelCloseButton">
<Anchors>
<Anchor point="TOPRIGHT" relativePoint="TOPRIGHT">
<Offset x="4" y="5"/>
</Anchor>
</Anchors>
</Button>
</Frames>
</Frame>
<Frame name="ButtonFrameTemplate" inherits="PortraitFrameTemplate" virtual="true">
<Layers>
<Layer level="BORDER">
<Texture name="$parentBtnCornerLeft" inherits="UI-Frame-BtnCornerLeft">
<Anchors>
<Anchor point="BOTTOMLEFT" x="-2" y="-1"/>
</Anchors>
</Texture>
<Texture name="$parentBtnCornerRight" inherits="UI-Frame-BtnCornerRight">
<Anchors>
<Anchor point="BOTTOMRIGHT" x="0" y="-1"/>
</Anchors>
</Texture>
<Texture name="$parentButtonBottomBorder" inherits="_UI-Frame-BtnBotTile">
<Anchors>
<Anchor point="BOTTOMLEFT" relativeTo="$parentBtnCornerLeft" relativePoint="BOTTOMRIGHT" y="3"/>
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBtnCornerRight" relativePoint="BOTTOMLEFT"/>
</Anchors>
</Texture>
</Layer>
</Layers>
<Frames>
<Frame name="$parentInset" useParentLevel="true" inherits="InsetFrameTemplate" parentKey="Inset">
<Anchors>
<Anchor point="TOPLEFT" x="4" y="-60" />
<Anchor point="BOTTOMRIGHT" x="-6" y="26" />
</Anchors>
</Frame>
</Frames>
</Frame>
<Button name="MagicButtonTemplate" inherits="UIPanelButtonTemplate2" virtual="true">
<Size x="80" y="22"/>
<Scripts>
<OnLoad function="MagicButton_OnLoad" />
</Scripts>
</Button>
<Slider name="UIPanelScrollBarTrimTemplate" virtual="true">
<Size>
<AbsDimension x="20" y="0"/>
</Size>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentBG" setAllPoints="true" hidden="true">
<Color r="0" g="0" b="0" a=".85"/>
</Texture>
</Layer>
<Layer level="ARTWORK">
<Texture name="$parentTop" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
<Size>
<AbsDimension x="24" y="48"/>
</Size>
<Anchors>
<Anchor point="TOPLEFT">
<Offset>
<AbsDimension x="-4" y="17"/>
</Offset>
</Anchor>
</Anchors>
<TexCoords left="0" right="0.45" top="0" bottom=".20"/>
</Texture>
<Texture name="$parentBottom" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
<Size>
<AbsDimension x="24" y="64"/>
</Size>
<Anchors>
<Anchor point="BOTTOMLEFT">
<Offset>
<AbsDimension x="-4" y="-15"/>
</Offset>
</Anchor>
</Anchors>
<TexCoords left="0.515625" right="0.97" top="0.1440625" bottom="0.4140625"/>
</Texture>
<Texture name="$parentMiddle" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="$parentTop" relativePoint="BOTTOMLEFT"/>
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBottom" relativePoint="TOPRIGHT"/>
</Anchors>
<TexCoords left="0" right="0.45" top="0.1640625" bottom="1"/>
</Texture>
</Layer>
</Layers>
<Frames>
<Button name="$parentScrollUpButton" inherits="UIPanelScrollUpButtonTemplate">
<Anchors>
<Anchor point="BOTTOM" relativePoint="TOP" x="0" y="-2"/>
</Anchors>
<Scripts>
<OnClick>
local parent = self:GetParent();
local scrollStep = self:GetParent().scrollStep or (parent:GetHeight() / 2);
parent:SetValue(parent:GetValue() - scrollStep);
PlaySound("UChatScrollButton");
</OnClick>
</Scripts>
</Button>
<Button name="$parentScrollDownButton" inherits="UIPanelScrollDownButtonTemplate">
<Anchors>
<Anchor point="TOP" relativePoint="BOTTOM" x="0" y="2"/>
</Anchors>
<Scripts>
<OnClick>
local parent = self:GetParent();
local scrollStep = self:GetParent().scrollStep or (parent:GetHeight() / 2);
parent:SetValue(parent:GetValue() + scrollStep);
PlaySound("UChatScrollButton");
</OnClick>
</Scripts>
</Button>
</Frames>
<Scripts>
<OnValueChanged>
self:GetParent():SetVerticalScroll(value);
</OnValueChanged>
</Scripts>
<ThumbTexture name="$parentThumbTexture" inherits="UIPanelScrollBarButton" file="Interface\Buttons\UI-ScrollBar-Knob">
<Size>
<AbsDimension x="18" y="24"/>
</Size>
<TexCoords left="0.20" right="0.80" top="0.125" bottom="0.875"/>
</ThumbTexture>
</Slider>
<EditBox name="SearchBoxTemplate" inherits="InputBoxTemplate" autoFocus="false" virtual="true">
<Layers>
<Layer level="OVERLAY">
<Texture name="$parentSearchIcon" file="Interface\Common\UI-Searchbox-Icon" parentKey="searchIcon">
<Size x="14" y="14"/>
<Anchors>
<Anchor point="LEFT" x="-" y="-2"/>
</Anchors>
</Texture>
</Layer>
</Layers>
<Frames>
<Button name="$parentClearButton" parentKey="clearButton" hidden="true">
<Size x="17" y="17"/>
<Anchors>
<Anchor point="RIGHT" x="-3" y="0"/>
</Anchors>
<Layers>
<Layer level="ARTWORK">
<Texture file="Interface\FriendsFrame\ClearBroadcastIcon" alpha="0.5" parentKey="texture">
<Size>
<AbsDimension x="17" y="17"/>
</Size>
<Anchors>
<Anchor point="TOPLEFT" x="0" y="0"/>
</Anchors>
</Texture>
</Layer>
</Layers>
<Scripts>
<OnEnter>
self.texture:SetAlpha(1.0);
</OnEnter>
<OnLeave>
self.texture:SetAlpha(0.5);
</OnLeave>
<OnMouseDown>
if self:IsEnabled() then
self.texture:SetPoint("TOPLEFT", 1, -1);
end
</OnMouseDown>
<OnMouseUp>
self.texture:SetPoint("TOPLEFT", 0, 0);
</OnMouseUp>
<OnClick>
PlaySound("igMainMenuOptionCheckBoxOn");
local editBox = self:GetParent();
if editBox.clearFunc then
editBox.clearFunc(editBox);
end
editBox:SetText("");
if not editBox:HasFocus() then
editBox:GetScript("OnEditFocusLost")(editBox);
end
editBox:ClearFocus();
</OnClick>
</Scripts>
</Button>
</Frames>
<Scripts>
<OnLoad function="SearchBoxTemplate_OnLoad"/>
<OnEscapePressed function="EditBox_ClearFocus"/>
<OnEditFocusLost function="SearchBoxTemplate_OnEditFocusLost"/>
<OnEditFocusGained function="SerachBoxTemplate_OnEditFocusGained"/>
</Scripts>
</EditBox>
<Frame name="TooltipBorderedFrameTemplate" virtual="true">
<Layers>
<Layer level="BACKGROUND">
<Texture parentKey="BorderTopLeft" file="Interface\Tooltips\UI-Tooltip-TL">
<Size x="8" y="8"/>
<Anchors>
<Anchor point="TOPLEFT"/>
</Anchors>
</Texture>
<Texture parentKey="BorderTopRight" file="Interface\Tooltips\UI-Tooltip-TR">
<Size x="8" y="8"/>
<Anchors>
<Anchor point="TOPRIGHT"/>
</Anchors>
</Texture>
<Texture parentKey="BorderBottomRight" file="Interface\Tooltips\UI-Tooltip-BR">
<Size x="8" y="8"/>
<Anchors>
<Anchor point="BOTTOMRIGHT"/>
</Anchors>
</Texture>
<Texture parentKey="BorderBottomLeft" file="Interface\Tooltips\UI-Tooltip-BL">
<Size x="8" y="8"/>
<Anchors>
<Anchor point="BOTTOMLEFT"/>
</Anchors>
</Texture>
<Texture parentKey="BorderTop" file="Interface\Tooltips\UI-Tooltip-T">
<Size x="8" y="8"/>
<Anchors>
<Anchor point="TOPLEFT" relativeKey="$parent.BorderTopLeft" relativePoint="TOPRIGHT"/>
<Anchor point="TOPRIGHT" relativeKey="$parent.BorderTopRight" relativePoint="TOPLEFT"/>
</Anchors>
</Texture>
<Texture parentKey="BorderRight" file="Interface\Tooltips\UI-Tooltip-R">
<Size x="8" y="8"/>
<Anchors>
<Anchor point="TOPRIGHT" relativeKey="$parent.BorderTopRight" relativePoint="BOTTOMRIGHT"/>
<Anchor point="BOTTOMRIGHT" relativeKey="$parent.BorderBottomRight" relativePoint="TOPRIGHT"/>
</Anchors>
</Texture>
<Texture parentKey="BorderBottom" file="Interface\Tooltips\UI-Tooltip-B">
<Size x="8" y="8"/>
<Anchors>
<Anchor point="BOTTOMLEFT" relativeKey="$parent.BorderBottomLeft" relativePoint="BOTTOMRIGHT"/>
<Anchor point="BOTTOMRIGHT" relativeKey="$parent.BorderBottomRight" relativePoint="BOTTOMLEFT"/>
</Anchors>
</Texture>
<Texture parentKey="BorderLeft" file="Interface\Tooltips\UI-Tooltip-L">
<Size x="8" y="8"/>
<Anchors>
<Anchor point="TOPLEFT" relativeKey="$parent.BorderTopLeft" relativePoint="BOTTOMLEFT"/>
<Anchor point="BOTTOMLEFT" relativeKey="$parent.BorderBottomLeft" relativePoint="TOPLEFT"/>
</Anchors>
</Texture>
<Texture parentKey="Background">
<Anchors>
<Anchor point="TOPLEFT" relativeKey="$parent.BorderTopLeft" relativePoint="BOTTOMRIGHT"/>
<Anchor point="BOTTOMRIGHT" relativeKey="$parent.BorderBottomRight" relativePoint="TOPLEFT"/>
</Anchors>
<Color r="0" g="0" b="0" a="0.8"/>
</Texture>
</Layer>
</Layers>
</Frame>
<Script file="Core.lua"/>
<Script file="GUI.lua"/>
<Script file="Preview.lua"/>
<Script file="Links.lua"/>
<Script file="URL.lua"/>
<Script file="Tooltip.lua"/>
<Script file="Options.lua"/>
<Script file="Templates.lua"/>
<Script file="Enchants.lua"/>
<Include file="Filters\Filters.xml"/>
<Include file="Sorting\Sorting.xml"/>
</Ui>

316
MogIt/Core/Enchants.lua Normal file
View File

@@ -0,0 +1,316 @@
local _, MogIt = ...
MogIt.enchants = {
{
{
id = 2564,
name = "Agility",
},
{
id = 2646,
name = "Agility (2H)",
},
{
id = 1900,
name = "Crusader",
},
{
id = 912,
name = "Demonslaying",
},
{
id = 803,
name = "Fiery Weapon",
},
{
id = 963,
name = "Greater Impact (2H)",
},
{
id = 805,
name = "Greater Striking",
},
{
id = 2505,
name = "Healing power",
},
{
id = 1894,
name = "Icy Chill",
},
{
id = 1897,
name = "Impact (2H)",
},
{
id = 853,
name = "Lesser Beastslayer",
},
{
id = 854,
name = "Lesser Elemental Slayer",
},
{
id = 943,
name = "Lesser Impact (2H)",
},
{
id = 723,
name = "Lesser Intellect (2H)",
},
{
id = 255,
name = "Lesser Spirit (2H)",
},
{
id = 241,
name = "Lesser Striking",
},
{
id = 1898,
name = "Lifestealing",
},
{
id = 1904,
name = "Major Intellect (2H)",
},
{
id = 1903,
name = "Major Spirit (2H)",
},
{
id = 2568,
name = "Mighty Intellect",
},
{
id = 2567,
name = "Mighty Spirit",
},
{
id = 249,
name = "Minor Beastslayer",
},
{
id = 241,
name = "Minor Impact (2H)",
},
{
id = 250,
name = "Minor Striking",
},
{
id = 2504,
name = "Spellpower",
},
{
id = 2563,
name = "Strength",
},
{
id = 943,
name = "Striking",
},
{
id = 1896,
name = "Superior Impact (2H)",
},
{
id = 1897,
name = "Superior Striking",
},
{
id = 1899,
name = "Unholy Weapon",
},
{
id = 2443,
name = "Winter's Might",
},
name = "Classic",
},
{
{
id = 2675,
name = "Battlemaster",
},
{
id = 3225,
name = "Executioner",
},
{
id = 2670,
name = "Major Agility (2H)",
},
{
id = 3846,
name = "Major Healing",
},
{
id = 2666,
name = "Major Intellect",
},
{
id = 2669,
name = "Major Spellpower",
},
{
id = 963,
name = "Major Striking",
},
{
id = 2673,
name = "Mongoose",
},
{
id = 2668,
name = "Potency",
},
{
id = 2667,
name = "Savagery (2H)",
},
{
id = 2672,
name = "Soulfrost",
},
{
id = 2674,
name = "Spellsurge",
},
{
id = 2671,
name = "Sunfire",
},
name = "The Burning Crusade",
},
{
{
id = 3788,
name = "Accuracy",
},
{
id = 3789,
name = "Beserking",
},
{
id = 3790,
name = "Black Magic",
},
{
id = 3869,
name = "Blade Ward",
},
{
id = 3870,
name = "Blood Draining",
},
{
id = 3273,
name = "Deathfrost",
},
{
id = 1103,
name = "Exceptional Agility",
},
{
id = 3830,
name = "Exceptional Spellpower",
},
{
id = 3844,
name = "Exceptional Spirit",
},
{
id = 3251,
name = "Giant Slayer",
},
{
id = 3222,
name = "Greater Agility",
},
{
id = 1606,
name = "Greater Potency",
},
{
id = 3828,
name = "Greater Savagery (2H)",
},
{
id = 3854,
name = "Greater Spellpower (Staff)",
},
{
id = 3239,
name = "Icebreaker",
},
{
id = 3241,
name = "Lifeward",
},
{
id = 3827,
name = "Massacre (2H)",
},
{
id = 3834,
name = "Mighty Spellpower",
},
{
id = 3247,
name = "Scourgebane (2H)",
},
{
id = 3855,
name = "Spellpower (Staff)",
},
{
id = 3833,
name = "Superior Potency",
},
name = "Wrath of the Lich King",
},
{
{
id = 3369,
name = "Rune of Cinderglacier",
},
{
id = 3366,
name = "Rune of Lichbane",
},
{
id = 3370,
name = "Rune of Razorice",
},
{
id = 3595,
name = "Rune of Spellbreaking (1H)",
},
{
id = 3367,
name = "Rune of Spellshattering (2H)",
},
{
id = 3594,
name = "Rune of Swordbreaking (1H)",
},
{
id = 3365,
name = "Rune of Swordshattering (2H)",
},
{
id = 3368,
name = "Rune of the Fallen Crusader",
},
{
id = 3883,
name = "Rune of the Nerubian Carapace (1H)",
},
{
id = 3847,
name = "Rune of the Stoneskin Gargoyle (2H)",
},
name = "Runeforging",
},
}

View File

@@ -0,0 +1,174 @@
local MogIt,mog = ...;
local L = mog.L;
mog.filters = {};
function mog:CreateFilter(name,frame)
if not name or mog.filters[name] then return end;
if frame then
frame:SetParent(mog.filt.frame);
else
frame = CreateFrame("Frame",nil,mog.filt.frame);
end
frame:Hide();
mog.filters[name] = frame;
return frame;
end
function mog:GetFilter(name)
return mog.filters[name];
end
mog.filt = CreateFrame("Frame","MogItFilters",mog.frame,"ButtonFrameTemplate");
mog.filt:Hide();
mog.filt:SetPoint("TOPLEFT",mog.frame,"TOPRIGHT");
mog.filt:SetSize(200,300);
mog.filt:SetClampedToScreen(true);
mog.filt:EnableMouse(true);
--MogItFiltersCloseButton:SetNormalTexture("Interface\\BUTTONS\\UI-Panel-HideButton-Up");
--MogItFiltersCloseButton:SetPushedTexture("Interface\\BUTTONS\\UI-Panel-HideButton-Down");
MogItFiltersBg:SetTexture("Interface\\AddOns\\MogIt\\FrameGeneral\\UI-Background-Rock",true);
MogItFiltersBg:SetVertexColor(0.8,0.3,0.8);
MogItFiltersTitleText:SetText(FILTERS);
mog.filt.portrait:Hide();
mog.filt.portraitFrame:Hide();
mog.filt.topLeftCorner:Show();
mog.filt.topBorderBar:SetPoint("TOPLEFT", mog.filt.topLeftCorner, "TOPRIGHT", 0, 0);
mog.filt.leftBorderBar:SetPoint("TOPLEFT", mog.filt.topLeftCorner, "BOTTOMLEFT", 0, 0);
--ButtonFrameTemplate_HidePortrait(mog.filt);
mog.filt.results = mog.filt:CreateFontString(nil,"ARTWORK","GameFontNormal");
mog.filt.results:SetPoint("TOPLEFT",mog.filt,"TOPLEFT",10,-35);
mog.filt.results:SetText(L["Results"]..":");
mog.filt.models = mog.filt:CreateFontString(nil,"ARTWORK","GameFontHighlight");
mog.filt.models:SetPoint("LEFT",mog.filt.results,"RIGHT",5,0);
mog.filt.defaults = CreateFrame("Button","MogItFrameFiltersDefaults",mog.filt,"MagicButtonTemplate");
mog.filt.defaults:SetPoint("BOTTOMLEFT",mog.filt,"BOTTOMLEFT",5,5);
mog.filt.defaults:SetWidth(100);
mog.filt.defaults:SetText(DEFAULTS);
mog.filt.defaults:SetScript("OnClick",function(self,btn)
if mog.active and mog.active.filters then
for k,v in ipairs(mog.active.filters) do
if mog.filters[v] and mog.filters[v].Default then
mog.filters[v].Default();
end
end
mog:BuildList();
end
end);
mog.filt.scroll = CreateFrame("ScrollFrame","MogItFiltersScroll",mog.filt,"UIPanelScrollFrameTemplate");
mog.filt.scroll:SetPoint("TOPLEFT",mog.filt.Inset,"TOPLEFT",0,-3);
mog.filt.scroll:SetPoint("BOTTOMRIGHT",mog.filt.Inset,"BOTTOMRIGHT",-23,2);
mog.filt.scroll:Hide();
mog.filt.scroll.ScrollBar = MogItFiltersScrollScrollBar
mog.filt.scroll.ScrollBar.top = mog.filt.scroll.ScrollBar:CreateTexture(nil,"ARTWORK");
mog.filt.scroll.ScrollBar.top:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar");
mog.filt.scroll.ScrollBar.top:SetSize(24,48);
mog.filt.scroll.ScrollBar.top:SetPoint("TOPLEFT",mog.filt.scroll.ScrollBar,"TOPLEFT",-6,19);
mog.filt.scroll.ScrollBar.top:SetTexCoord(0,0.45,0,0.2);
mog.filt.scroll.ScrollBar.bottom = mog.filt.scroll.ScrollBar:CreateTexture(nil,"ARTWORK");
mog.filt.scroll.ScrollBar.bottom:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar");
mog.filt.scroll.ScrollBar.bottom:SetSize(24,64);
mog.filt.scroll.ScrollBar.bottom:SetPoint("BOTTOMLEFT",mog.filt.scroll.ScrollBar,"BOTTOMLEFT",-6,-17);
mog.filt.scroll.ScrollBar.bottom:SetTexCoord(0.515625,0.97,0.1440625,0.4140625);
mog.filt.scroll.ScrollBar.middle = mog.filt.scroll.ScrollBar:CreateTexture(nil,"ARTWORK");
mog.filt.scroll.ScrollBar.middle:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar");
mog.filt.scroll.ScrollBar.middle:SetPoint("TOPLEFT",mog.filt.scroll.ScrollBar.top,"BOTTOMLEFT");
mog.filt.scroll.ScrollBar.middle:SetPoint("BOTTOMRIGHT",mog.filt.scroll.ScrollBar.bottom,"TOPRIGHT");
mog.filt.scroll.ScrollBar.middle:SetTexCoord(0,0.45,0.1640625,1);
mog.filt.frame = CreateFrame("Frame","MogItFiltersScrollFrame",mog.filt);
mog.filt.scroll:SetScrollChild(mog.filt.frame);
mog.filt.frame:SetWidth(180);
mog.filt.error = mog.filt:CreateFontString(nil,"ARTWORK","GameFontRed");
mog.filt.error:SetPoint("TOPLEFT",mog.filt.Inset,"TOPLEFT",7,-5);
mog.filt.error:SetPoint("BOTTOMRIGHT",mog.filt.Inset,"BOTTOMRIGHT",-7,5);
--mog.filt.error:SetJustifyV("TOP");
mog.filt.error:SetText(L["No module is selected"]);
function mog:FilterUpdate()
if not mog.active then
mog.filt.scroll:Hide();
mog.filt.error:SetText(L["No module is selected"]);
mog.filt.error:Show();
return;
elseif not mog.active.filters then
mog.filt.scroll:Hide();
mog.filt.error:SetText(L["This module has no filters"]);
mog.filt.error:Show();
return;
end
mog.filt.scroll:Show();
mog.filt.error:Hide();
for k,v in pairs(mog.filters) do
v:Hide();
end
local height = 20;
local last;
for k,v in ipairs(mog.active.filters) do
local filter = mog.filters[v];
if filter and (not filter.slot or (mog.active.active and filter.slot == mog.active.active.label)) then
filter:ClearAllPoints();
if last then
filter:SetPoint("TOPLEFT",last,"BOTTOMLEFT",0,-14);
else
filter:SetPoint("TOPLEFT",mog.filt.frame,"TOPLEFT",12,-10);
end
filter:SetPoint("RIGHT",mog.filt.frame,"RIGHT",-19,0);
if not filter.bg then
filter.bg = mog.filters[v]:CreateTexture(nil,"BACKGROUND");
filter.bg:SetPoint("TOPLEFT",mog.filters[v],"TOPLEFT",-5,5);
filter.bg:SetPoint("BOTTOMRIGHT",mog.filters[v],"BOTTOMRIGHT",5,-5);
filter.bg:SetTexture(0.3,0.3,0.3,0.2);
end
height = height + filter:GetHeight() + (last and 14 or 0);
last = filter;
filter:Show();
end
end
mog.filt.frame:SetHeight(height);
end
function mog:CheckFilters(module,value)
if module.filters and module.GetFilterArgs then
for _,filter in ipairs(module.filters) do
local filterObject = mog:GetFilter(filter);
if (not filterObject.slot or (module.active and filterObject.slot == module.active.label)) and not filterObject.Filter(module.GetFilterArgs(filter,value)) then
return;
end
end
end
return true;
end
--[[
VENDOR?
Valor Points
Justice Points
Conquest Points
Honor Points
Tier Tokens
--> Tier 1
--> Tier 2
--> etc
Gold
Other
ZONES
-- current zone
NAME
QUEST/ACHI
- complete?
--]]

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Ui xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.blizzard.com/wow/ui/" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="Filters.lua"/>
<Script file="name.lua"/>
<Script file="level.lua"/>
<Script file="itemLevel.lua"/>
<Script file="faction.lua"/>
<Script file="class.lua"/>
<Script file="source.lua"/>
<Script file="slot.lua"/>
<Script file="quality.lua"/>
<Script file="bind.lua"/>
<Script file="hasItem.lua"/>
<Script file="chestType.lua"/>
<Script file="sheath.lua"/>
</Ui>

View File

@@ -0,0 +1,80 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("bind");
local selected;
local num;
local all;
f:SetHeight(41);
f.bind = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
f.bind:SetPoint("TOPLEFT",f,"TOPLEFT",0,0);
f.bind:SetPoint("RIGHT",f,"RIGHT",0,0);
f.bind:SetText(L["Bind"]..":");
f.bind:SetJustifyH("LEFT");
f.dd = CreateFrame("Frame","MogItFiltersBindDropdown",f,"UIDropDownMenuTemplate");
f.dd:SetPoint("TOPLEFT",f.bind,"BOTTOMLEFT",-16,-2);
UIDropDownMenu_SetWidth(f.dd,125);
UIDropDownMenu_SetButtonWidth(f.dd,140);
UIDropDownMenu_JustifyText(f.dd,"LEFT");
function f.dd.SelectAll(self)
num = 0;
for k,v in ipairs(L.bind) do
selected[k] = all;
num = num + (all and 1 or 0);
end
all = not all;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
ToggleDropDownMenu(1,nil,f.dd);
mog:BuildList();
end
function f.dd.Tier1(self)
if selected[self.value] and (not self.checked) then
num = num - 1;
elseif (not selected[self.value]) and self.checked then
num = num + 1;
end
selected[self.value] = self.checked;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
mog:BuildList();
end
function f.dd.initialize(self)
local info;
info = UIDropDownMenu_CreateInfo();
info.text = all and L["Select All"] or L["Select None"];
info.func = f.dd.SelectAll;
info.notCheckable = true;
UIDropDownMenu_AddButton(info);
for k,v in ipairs(L.bind) do
info = UIDropDownMenu_CreateInfo();
info.text = v;
info.value = k;
info.func = f.dd.Tier1;
info.keepShownOnClick = true;
info.isNotRadio = true;
info.checked = selected[k];
UIDropDownMenu_AddButton(info);
end
end
function f.Filter(bind)
return ((not bind) and selected[1]) or selected[bind];
end
function f.Default()
selected = {};
num = 0;
all = nil;
for k,v in ipairs(L.bind) do
selected[k] = true;
num = num + 1;
end
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
end
f.Default();

View File

@@ -0,0 +1,62 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("chestType");
local selected;
f:SetHeight(41);
f.slot = "Chest";
f.chestType = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
f.chestType:SetPoint("TOPLEFT",f,"TOPLEFT",0,0);
f.chestType:SetPoint("RIGHT",f,"RIGHT",0,0);
f.chestType:SetText(L["Chest type"]..":");
f.chestType:SetJustifyH("LEFT");
local function onClick(self, invType)
selected = invType;
f.dd:SetText(self.value);
mog:BuildList();
end
local labels = {
L["Any"],
L["Tunic"],
L["Robe"],
}
local invTypes = {
nil,
"INVTYPE_CHEST",
"INVTYPE_ROBE",
}
f.dd = mog:CreateDropdown("Frame", f);
f.dd:SetPoint("TOPLEFT",f.chestType,"BOTTOMLEFT",-16,-2);
f.dd:SetWidth(125);
f.dd:SetButtonWidth(140);
f.dd:JustifyText("LEFT");
f.dd.initialize = function(self)
for i,v in ipairs(labels) do
local info = UIDropDownMenu_CreateInfo();
info.text = v;
info.func = onClick;
info.arg1 = invTypes[i]
info.checked = invTypes[i] == selected;
UIDropDownMenu_AddButton(info);
end
end
function f.Filter(item)
if not selected then
return true;
end
local item = mog:GetItemInfo(item, "BuildList");
return not item or selected == item.invType;
end
function f.Default()
selected = nil;
f.dd:SetText(L["Any"]);
end
f.Default();

View File

@@ -0,0 +1,98 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("class");
local coords = CLASS_ICON_TCOORDS;
local colours = RAID_CLASS_COLORS;
local class;
local selected;
local num;
local all;
f:SetHeight(41);
f.class = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
f.class:SetPoint("TOPLEFT",f,"TOPLEFT",0,0);
f.class:SetPoint("RIGHT",f,"RIGHT",0,0);
f.class:SetText(CLASS..":");
f.class:SetJustifyH("LEFT");
f.dd = CreateFrame("Frame","MogItFiltersClassDropdown",f,"UIDropDownMenuTemplate");
f.dd:SetPoint("TOPLEFT",f.class,"BOTTOMLEFT",-16,-2);
UIDropDownMenu_SetWidth(f.dd,125);
UIDropDownMenu_SetButtonWidth(f.dd,140);
UIDropDownMenu_JustifyText(f.dd,"LEFT");
function f.dd.SelectAll(self)
num = 0;
class = 0;
for k,v in pairs(LOCALIZED_CLASS_NAMES_MALE) do
selected[k] = all;
num = num + (all and 1 or 0);
class = class + (all and L.classBits[k] or 0);
end
all = not all;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
ToggleDropDownMenu(1,nil,f.dd);
mog:BuildList();
end
function f.dd.Tier1(self)
if selected[self.value] and (not self.checked) then
class = class - L.classBits[self.value];
num = num - 1;
elseif (not selected[self.value]) and self.checked then
class = class + L.classBits[self.value];
num = num + 1;
end
selected[self.value] = self.checked;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
mog:BuildList();
end
function f.dd.initialize(self)
local info;
info = UIDropDownMenu_CreateInfo();
info.text = all and L["Select All"] or L["Select None"];
info.func = f.dd.SelectAll;
info.notCheckable = true;
UIDropDownMenu_AddButton(info);
for k,v in pairs(LOCALIZED_CLASS_NAMES_MALE) do
info = UIDropDownMenu_CreateInfo();
info.text = v;
info.value = k;
info.colorCode = string.format("\124cff%.2x%.2x%.2x",colours[k].r*255,colours[k].g*255,colours[k].b*255);
info.func = f.dd.Tier1;
info.keepShownOnClick = true;
info.isNotRadio = true;
info.checked = selected[k];
info.icon = "Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes";
info.tCoordLeft = coords[k][1];
info.tCoordRight = coords[k][2];
info.tCoordTop = coords[k][3];
info.tCoordBottom = coords[k][4];
UIDropDownMenu_AddButton(info);
end
end
function f.Filter(input)
return (not input) or (bit.band(class,input)>0);
end
function f.Default()
--[[
class = L.classBits[select(2,UnitClass("PLAYER"))];
selected = {[select(2,UnitClass("PLAYER"))] = true};
num = 1;
all = true;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
--]]
class = 1535
selected = {}
for i=1,10 do selected[CLASS_SORT_ORDER[i]] = true end
num = 10;
all = false;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
end
f.Default();

View File

@@ -0,0 +1,59 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("faction");
local alliance;
local horde;
local factions = {
[1] = "Alliance",
[2] = "Horde",
}
-- Disabled default faction check, with faction check enabled, these need to be false.
local settings = {
Alliance = true,
Horde = true,
}
f:SetHeight(69);
f.faction = f:CreateFontString(nil,nil,"GameFontHighlightSmall");
f.faction:SetPoint("TOPLEFT");
f.faction:SetPoint("RIGHT");
f.faction:SetText(L["Faction"]..":");
f.faction:SetJustifyH("LEFT");
local function onClick(self)
settings[self.value] = self:GetChecked() == 1;
mog:BuildList();
end
f.Alliance = CreateFrame("CheckButton","MogItCoreFiltersFactionAlliance",f,"UICheckButtonTemplate");
f.Alliance.text = MogItCoreFiltersFactionAllianceText
f.Alliance.text:SetText(FACTION_ALLIANCE);
f.Alliance:SetPoint("TOPLEFT",f.faction,"BOTTOMLEFT");
f.Alliance:SetScript("OnClick",onClick);
f.Alliance.value = "Alliance";
f.Horde = CreateFrame("CheckButton","MogItCoreFiltersFactionHorde",f,"UICheckButtonTemplate");
f.Horde.text = MogItCoreFiltersFactionHordeText
f.Horde.text:SetText(FACTION_HORDE);
f.Horde:SetPoint("TOPLEFT",f.Alliance,"BOTTOMLEFT");
f.Horde:SetScript("OnClick",onClick);
f.Horde.value = "Horde";
function f.Filter(faction)
return (not faction) or (settings[factions[faction]]);
end
function f.Default()
-- for i, faction in ipairs(factions) do
-- local value = UnitFactionGroup("PLAYER") == faction;
-- settings[faction] = value;
-- f[faction]:SetChecked(value);
-- end
f.Alliance:SetChecked(true);
f.Horde:SetChecked(true);
end
f.Default();

View File

@@ -0,0 +1,32 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("hasItem");
local enabled;
f:SetHeight(41);
f.label = f:CreateFontString(nil,nil,"GameFontHighlightSmall");
f.label:SetPoint("TOPLEFT");
f.label:SetPoint("RIGHT");
f.label:SetText(L["Owned items"]..":");
f.label:SetJustifyH("LEFT");
f.hasItem = CreateFrame("CheckButton","MogItCoreFiltersHasItem",f,"UICheckButtonTemplate");
f.hasItem.text = MogItCoreFiltersHasItemText
f.hasItem.text:SetText(L["Only items you own"]);
f.hasItem:SetPoint("TOPLEFT",f.label,"BOTTOMLEFT");
f.hasItem:SetScript("OnClick",function(self)
enabled = self:GetChecked() == 1;
mog:BuildList();
end);
function f.Filter(itemID)
return not enabled or mog:HasItem(itemID);
end
function f.Default()
f.hasItem:SetChecked(false);
enabled = false;
end
f.Default();

View File

@@ -0,0 +1,66 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("itemLevel");
local minlvl;
local maxlvl;
f:SetHeight(35);
f.label = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
f.label:SetPoint("TOPLEFT",f,"TOPLEFT",0,0);
f.label:SetPoint("RIGHT",f,"RIGHT",0,0);
f.label:SetText("Item level"..":");
f.label:SetJustifyH("LEFT");
f.min = CreateFrame("EditBox","MogItFiltersItemLevelMin",f,"InputBoxTemplate");
f.min:SetSize(32,16);
f.min:SetPoint("TOPLEFT",f.label,"BOTTOMLEFT",8,-5);
f.min:SetNumeric(true);
f.min:SetMaxLetters(3);
f.min:SetAutoFocus(false);
f.min:SetScript("OnEnterPressed",EditBox_ClearFocus);
f.min:SetScript("OnTabPressed",function(self)
f.max:SetFocus();
end);
f.min:SetScript("OnTextChanged",function(self,user)
if user then
minlvl = self:GetNumber() or 0;
mog:BuildList();
end
end);
f.dash = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
f.dash:SetPoint("LEFT",f.min,"RIGHT",0,1);
f.dash:SetText("-");
f.max = CreateFrame("EditBox","MogItFiltersItemLevelMax",f,"InputBoxTemplate");
f.max:SetSize(32,16);
f.max:SetPoint("LEFT",f.min,"RIGHT",12,0);
f.max:SetNumeric(true);
f.max:SetMaxLetters(3);
f.max:SetAutoFocus(false);
f.max:SetScript("OnEnterPressed",EditBox_ClearFocus);
f.max:SetScript("OnTabPressed",function(self)
f.min:SetFocus();
end);
f.max:SetScript("OnTextChanged",function(self,user)
if user then
maxlvl = self:GetNumber() or 0;
mog:BuildList();
end
end);
function f.Filter(lvl)
local lvl = lvl or 0;
return (minlvl <= 0 or lvl >= minlvl) and (maxlvl <= 0 or lvl <= maxlvl);
end
function f.Default()
minlvl = 0;
f.min:SetNumber(minlvl);
maxlvl = 0;
f.max:SetNumber(maxlvl);
end
f.Default();

View File

@@ -0,0 +1,98 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("level");
local minlvl;
local maxlvl;
f:SetHeight(35);
f.label = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
f.label:SetPoint("TOPLEFT",f,"TOPLEFT",0,0);
f.label:SetPoint("RIGHT",f,"RIGHT",0,0);
f.label:SetText(LEVEL_RANGE..":");
f.label:SetJustifyH("LEFT");
f.min = CreateFrame("EditBox","MogItFiltersLevelMin",f,"InputBoxTemplate");
f.min:SetSize(25,16);
f.min:SetPoint("TOPLEFT",f.label,"BOTTOMLEFT",8,-5);
f.min:SetNumeric(true);
f.min:SetMaxLetters(2);
f.min:SetAutoFocus(false);
f.min:SetScript("OnEnterPressed",EditBox_ClearFocus);
f.min:SetScript("OnTabPressed",function(self)
f.max:SetFocus();
end);
f.min:SetScript("OnTextChanged",function(self,user)
if user then
minlvl = self:GetNumber() or 0;
mog:BuildList();
end
end);
f.dash = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
f.dash:SetPoint("LEFT",f.min,"RIGHT",0,1);
f.dash:SetText("-");
f.max = CreateFrame("EditBox","MogItFiltersLevelMax",f,"InputBoxTemplate");
f.max:SetSize(25,16);
f.max:SetPoint("LEFT",f.min,"RIGHT",12,0);
f.max:SetNumeric(true);
f.max:SetMaxLetters(2);
f.max:SetAutoFocus(false);
f.max:SetScript("OnEnterPressed",EditBox_ClearFocus);
f.max:SetScript("OnTabPressed",function(self)
f.min:SetFocus();
end);
f.max:SetScript("OnTextChanged",function(self,user)
if user then
maxlvl = self:GetNumber() or PLAYER_MAX_LEVEL;
mog:BuildList();
end
end);
function f.Filter(lvl)
lvl = lvl or 0;
return (lvl >= minlvl) and (lvl <= maxlvl);
end
function f.Default()
minlvl = 0;
f.min:SetNumber(minlvl);
maxlvl = UnitLevel("PLAYER");
f.max:SetNumber(maxlvl);
end
f.Default();
--[[
f.min:SetScript("OnEnterPressed",function(self)
self:ClearFocus();
minlvl = self:GetNumber() or 0;
mog:BuildList();
end);
f.min:SetScript("OnEscapePressed",function(self)
self:ClearFocus();
self:SetNumber(minlvl);
end);
f.min:SetScript("OnTabPressed",function(self)
f.max:SetFocus();
minlvl = self:GetNumber() or 0;
mog:BuildList();
end);
f.max:SetScript("OnEnterPressed",function(self)
self:ClearFocus();
maxlvl = self:GetNumber() or MAX_PLAYER_LEVEL;
mog:BuildList();
end);
f.max:SetScript("OnEscapePressed",function(self)
self:ClearFocus();
self:SetNumber(maxlvl);
end);
f.max:SetScript("OnTabPressed",function(self)
f.min:SetFocus();
maxlvl = self:GetNumber() or MAX_PLAYER_LEVEL;
mog:BuildList();
end);
--]]

View File

@@ -0,0 +1,45 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("name");
local name;
f:SetHeight(35);
f.label = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
f.label:SetPoint("TOPLEFT",f,"TOPLEFT",0,0);
f.label:SetPoint("RIGHT",f,"RIGHT",0,0);
f.label:SetText(NAME..":");
f.label:SetJustifyH("LEFT");
f.edit = CreateFrame("EditBox","MogItFiltersName",f,"SearchBoxTemplate");
f.edit:SetHeight(16);
f.edit:SetPoint("TOPLEFT",f.label,"BOTTOMLEFT",8,-5);
f.edit:SetPoint("RIGHT",f.label,"RIGHT",-2,0);
f.edit:SetAutoFocus(false);
--[[f.edit:SetScript("OnFocusGained",function(self)
end);--]]
f.edit:SetScript("OnEnterPressed",EditBox_ClearFocus);
f.edit:SetScript("OnTextChanged",function(self,user)
if user then
name = self:GetText() or "";
name = name:lower();
mog:BuildList();
end
end);
function f.edit.clearFunc(self)
name = "";
mog:BuildList();
end
function f.Filter(item)
item = item or "";
return (name == "") or (item:lower():find(name,nil,true));
end
function f.Default()
name = "";
f.edit:SetText(name);
end
f.Default();

View File

@@ -0,0 +1,82 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("quality");
local colours = ITEM_QUALITY_COLORS;
local selected;
local num;
local all;
f:SetHeight(41);
f.quality = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
f.quality:SetPoint("TOPLEFT",f,"TOPLEFT",0,0);
f.quality:SetPoint("RIGHT",f,"RIGHT",0,0);
f.quality:SetText(QUALITY..":");
f.quality:SetJustifyH("LEFT");
f.dd = CreateFrame("Frame","MogItFiltersQualityDropdown",f,"UIDropDownMenuTemplate");
f.dd:SetPoint("TOPLEFT",f.quality,"BOTTOMLEFT",-16,-2);
UIDropDownMenu_SetWidth(f.dd,125);
UIDropDownMenu_SetButtonWidth(f.dd,140);
UIDropDownMenu_JustifyText(f.dd,"LEFT");
function f.dd.SelectAll(self)
num = 0;
for k,v in ipairs(L.quality) do
selected[v] = all;
num = num + (all and 1 or 0);
end
all = not all;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
ToggleDropDownMenu(1,nil,f.dd);
mog:BuildList();
end
function f.dd.Tier1(self)
if selected[self.value] and (not self.checked) then
num = num - 1;
elseif (not selected[self.value]) and self.checked then
num = num + 1;
end
selected[self.value] = self.checked;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
mog:BuildList();
end
function f.dd.initialize(self)
local info;
info = UIDropDownMenu_CreateInfo();
info.text = all and L["Select All"] or L["Select None"];
info.func = f.dd.SelectAll;
info.notCheckable = true;
UIDropDownMenu_AddButton(info);
for i,v in ipairs(L.quality) do
info = UIDropDownMenu_CreateInfo();
info.text = _G["ITEM_QUALITY"..v.."_DESC"];
info.value = v;
info.colorCode = colours[v].hex;
info.func = f.dd.Tier1;
info.keepShownOnClick = true;
info.isNotRadio = true;
info.checked = selected[v];
UIDropDownMenu_AddButton(info);
end
end
function f.Filter(qual)
return (not qual) or selected[qual];
end
function f.Default()
selected = {};
num = 0;
all = nil;
for i,v in ipairs(L.quality) do
selected[v] = true;
num = num + 1;
end
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
end
f.Default();

View File

@@ -0,0 +1,83 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("sheath");
local selected;
local num;
local all;
f:SetHeight(41);
--f.slot = "Sword";
--f.slot = "Axe";
f.sheath = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
f.sheath:SetPoint("TOPLEFT",f,"TOPLEFT",0,0);
f.sheath:SetPoint("RIGHT",f,"RIGHT",0,0);
f.sheath:SetText(L["Sheath type"]..":");
f.sheath:SetJustifyH("LEFT");
f.dd = mog:CreateDropdown("Frame", f);
f.dd:SetPoint("TOPLEFT",f.sheath,"BOTTOMLEFT",-16,-2);
f.dd:SetWidth(125);
f.dd:SetButtonWidth(140);
f.dd:JustifyText("LEFT");
function f.dd.SelectAll(self)
num = 0;
for k,v in ipairs(L.sheath) do
selected[k] = all;
num = num + (all and 1 or 0);
end
all = not all;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
ToggleDropDownMenu(1,nil,f.dd);
mog:BuildList();
end
function f.dd.Tier1(self)
if selected[self.value] and (not self.checked) then
num = num - 1;
elseif (not selected[self.value]) and self.checked then
num = num + 1;
end
selected[self.value] = self.checked;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
mog:BuildList();
end
function f.dd.initialize(self)
local info;
info = UIDropDownMenu_CreateInfo();
info.text = all and L["Select All"] or L["Select None"];
info.func = f.dd.SelectAll;
info.notCheckable = true;
UIDropDownMenu_AddButton(info);
for k,v in ipairs(L.sheath) do
info = UIDropDownMenu_CreateInfo();
info.text = v;
info.value = k;
info.func = f.dd.Tier1;
info.keepShownOnClick = true;
info.isNotRadio = true;
info.checked = selected[k];
UIDropDownMenu_AddButton(info);
end
end
function f.Filter(sheath)
return (not sheath) or selected[sheath];
end
function f.Default()
selected = {};
num = 0;
all = nil;
for k,v in ipairs(L.sheath) do
selected[k] = true;
num = num + 1;
end
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
end
f.Default();

View File

@@ -0,0 +1,80 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("slot");
local selected;
local num;
local all;
f:SetHeight(41);
local slotLabel = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
slotLabel:SetPoint("TOPLEFT",f,"TOPLEFT",0,0);
slotLabel:SetPoint("RIGHT",f,"RIGHT",0,0);
slotLabel:SetText("Slots:");
slotLabel:SetJustifyH("LEFT");
f.dd = mog:CreateDropdown("Frame",f);
f.dd:SetPoint("TOPLEFT",slotLabel,"BOTTOMLEFT",-16,-2);
f.dd:SetWidth(125);
f.dd:SetButtonWidth(140);
f.dd:JustifyText("LEFT");
function f.dd.SelectAll(self)
num = 0;
for k,v in ipairs(L.slots) do
selected[k] = all;
num = num + (all and 1 or 0);
end
all = not all;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
ToggleDropDownMenu(1,nil,f.dd);
mog:BuildList();
end
function f.dd.Tier1(self)
if selected[self.value] and (not self.checked) then
num = num - 1;
elseif (not selected[self.value]) and self.checked then
num = num + 1;
end
selected[self.value] = self.checked;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
mog:BuildList();
end
function f.dd.initialize(self)
local info;
info = UIDropDownMenu_CreateInfo();
info.text = all and L["Select All"] or L["Select None"];
info.func = f.dd.SelectAll;
info.notCheckable = true;
UIDropDownMenu_AddButton(info);
for k,v in ipairs(L.slots) do
info = UIDropDownMenu_CreateInfo();
info.text = v;
info.value = k;
info.func = f.dd.Tier1;
info.keepShownOnClick = true;
info.isNotRadio = true;
info.checked = selected[k];
UIDropDownMenu_AddButton(info);
end
end
function f.Filter(slot)
return (not slot) or selected[slot];
end
function f.Default()
selected = {};
num = 0;
all = nil;
for k,v in ipairs(L.slots) do
selected[k] = true;
num = num + 1;
end
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
end
f.Default();

View File

@@ -0,0 +1,129 @@
local MogIt,mog = ...;
local L = mog.L;
local f = mog:CreateFilter("source");
local selected;
local sub;
local num;
local all;
f:SetHeight(41);
f.source = f:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
f.source:SetPoint("TOPLEFT",f,"TOPLEFT",0,0);
f.source:SetPoint("RIGHT",f,"RIGHT",0,0);
f.source:SetText(L["Source"]..":");
f.source:SetJustifyH("LEFT");
f.dd = CreateFrame("Frame","MogItFiltersSourceDropdown",f,"UIDropDownMenuTemplate");
f.dd:SetPoint("TOPLEFT",f.source,"BOTTOMLEFT",-16,-2);
UIDropDownMenu_SetWidth(f.dd,125);
UIDropDownMenu_SetButtonWidth(f.dd,140);
UIDropDownMenu_JustifyText(f.dd,"LEFT");
function f.dd.SelectAll(self)
num = 0;
for k,v in ipairs(L.source) do
selected[k] = all;
num = num + (all and 1 or 0);
end
all = not all;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
ToggleDropDownMenu(1,nil,f.dd);
mog:BuildList();
end
function f.dd.Tier1(self)
if selected[self.value] and (not self.checked) then
num = num - 1;
elseif (not selected[self.value]) and self.checked then
num = num + 1;
end
selected[self.value] = self.checked;
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
mog:BuildList();
end
function f.dd.Tier2(self)
sub[self.arg1][self.value] = self.checked;
if selected[self.arg1] then
mog:BuildList();
end
end
function f.dd.initialize(self,tier)
local info;
if tier == 1 then
info = UIDropDownMenu_CreateInfo();
info.text = all and L["Select All"] or L["Select None"];
info.func = f.dd.SelectAll;
info.notCheckable = true;
UIDropDownMenu_AddButton(info);
for k,v in ipairs(L.source) do
info = UIDropDownMenu_CreateInfo();
info.text = v;
info.value = k;
info.func = f.dd.Tier1;
info.keepShownOnClick = true;
info.isNotRadio = true;
info.checked = selected[k];
info.hasArrow = sub[k] and true;
UIDropDownMenu_AddButton(info);
end
elseif tier == 2 then
local parent = UIDROPDOWNMENU_MENU_VALUE;
if parent == 1 then
for k,v in ipairs(L.difficulties) do
info = UIDropDownMenu_CreateInfo();
info.text = v;
info.value = k;
info.func = f.dd.Tier2;
info.keepShownOnClick = true;
info.isNotRadio = true;
info.checked = sub[parent][k];
info.arg1 = parent;
UIDropDownMenu_AddButton(info,tier);
end
end
end
end
function f.Filter(src1,sub1)
if not src1 then
return true;
elseif selected[src1] then
if src1 == 1 then
if not sub1 then
return sub[1][8];
elseif sub1 == 7 then
return sub[1][3] or sub[1][5];
elseif sub1 == 8 then
return sub[1][4] or sub[1][6];
elseif sub1 == 9 then
return sub[1][7];
else
return sub[1][sub1];
end
end
return true;
end
end
function f.Default()
selected = {};
sub = {
[1] = {},
};
num = 0;
all = nil;
for k,v in ipairs(L.source) do
selected[k] = true;
num = num + 1;
end
for k,v in ipairs(L.difficulties) do
sub[1][k] = true;
end
UIDropDownMenu_SetText(f.dd,L["%d selected"]:format(num));
end
f.Default();

914
MogIt/Core/GUI.lua Normal file
View File

@@ -0,0 +1,914 @@
local MogIt,mog = ...;
local L = mog.L;
local useModel = {
[0] = TARGET,
[1] = PLAYER,
}
local myuseModel = UnitIsPlayer("PLAYER")
mog.playeruseModel = myuseModel;
mog.displayuseModel = myuseModel
local ModelFramePrototype = CreateFrame("Button")
local ModelFrame_MT = {__index = ModelFramePrototype}
--// mog.frame
mog.frame:SetPoint("CENTER");
mog.frame:SetSize(252,108);
mog.frame:SetToplevel(true);
mog.frame:SetClampedToScreen(true);
mog.frame:EnableMouse(true);
mog.frame:EnableMouseWheel(true);
mog.frame:SetMovable(true);
mog.frame:SetResizable(true);
mog.frame:SetDontSavePosition(true);
mog.frame:SetScript("OnMouseDown", mog.frame.StartMoving);
local function stopMovingOrSizing(self)
self:StopMovingOrSizing();
local profile = mog.db.profile;
profile.point, profile.x, profile.y = select(3, self:GetPoint());
end
mog.frame:SetScript("OnMouseUp", stopMovingOrSizing);
mog.frame:SetScript("OnHide", stopMovingOrSizing);
tinsert(UISpecialFrames,"MogItFrame");
mog.frame.TitleText:SetText("MogIt");
mog.frame.TitleText:SetPoint("RIGHT",mog.frame,"RIGHT",-28,0);
mog.frame.portrait:SetTexture("Interface\\AddOns\\MogIt\\Images\\MogIt");
mog.frame.portrait:SetTexCoord(0,106/128,0,105/128);
MogItFrameBg:SetTexture("Interface\\AddOns\\MogIt\\FrameGeneral\\UI-Background-Rock",true);
MogItFrameBg:SetVertexColor(0.8,0.3,0.8);
mog.frame.resize = CreateFrame("Button",nil,mog.frame);
mog.frame.resize:SetSize(16,16);
mog.frame.resize:SetPoint("BOTTOMRIGHT",-4,3);
mog.frame.resize:SetHitRectInsets(0, -4, 0, -3)
mog.frame.resize:SetScript("OnMouseDown", function(self)
mog.frame:SetMinResize(510,350);
mog.frame:SetMaxResize(GetScreenWidth(), GetScreenHeight());
mog.frame:StartSizing();
end);
local function stopMovingOrSizing()
mog.frame:StopMovingOrSizing();
end
mog.frame.resize:SetScript("OnMouseUp", stopMovingOrSizing);
mog.frame.resize:SetScript("OnHide", stopMovingOrSizing);
mog.frame.resize:SetNormalTexture([[Interface\ChatFrame\UI-ChatIM-SizeGrabber-Up]]);
mog.frame.resize:SetPushedTexture([[Interface\ChatFrame\UI-ChatIM-SizeGrabber-Down]])
mog.frame.resize:SetHighlightTexture([[Interface\ChatFrame\UI-ChatIM-SizeGrabber-Highlight]])
mog.frame.path = mog.frame:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
mog.frame.path:SetPoint("BOTTOMLEFT",mog.frame,"BOTTOMLEFT",17,10);
mog.frame.page = mog.frame:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
mog.frame.page:SetPoint("BOTTOMRIGHT",mog.frame,"BOTTOMRIGHT",-17,10);
--//
--// Model Frames
mog.models = {};
mog.modelBin = {};
mog.posX = 0;
mog.posY = 0;
mog.posZ = 0;
mog.face = 0;
function mog:CreateModelFrame(parent)
if mog.modelBin[1] then
local f = mog.modelBin[1];
f.parent = parent;
f:SetParent(parent);
--f:Show();
tremove(mog.modelBin,1);
return f;
end
local f = setmetatable(CreateFrame("Button",nil,parent), ModelFrame_MT);
f:Hide();
f.parent = parent;
f.data = {};
f.indicators = {};
f.model = CreateFrame("DressUpModel",nil,f);
f.model:SetAllPoints(f);
f.model:SetModelScale(2);
f.model:SetUnit("PLAYER");
f.model:SetPosition(0,0,0);
f.bg = f:CreateTexture(nil,"BACKGROUND");
f.bg:SetAllPoints(f);
f.bg:SetTexture(0.3,0.3,0.3,0.2);
f:RegisterForClicks("AnyUp");
f:RegisterForDrag("LeftButton","RightButton");
f:SetScript("OnShow",f.OnShow);
f:SetScript("OnHide",f.OnHide);
f:SetScript("OnUpdate",f.OnUpdate);
f:SetScript("OnDragStart",f.OnDragStart);
f:SetScript("OnDragStop",f.OnDragStop);
return f;
end
function mog:DeleteModelFrame(f)
f:Hide();
f:ClearAllPoints();
f:SetScript("OnClick",nil);
f:SetScript("OnEnter",nil);
f:SetScript("OnLeave",nil);
f:SetScript("OnMouseWheel",nil);
f:EnableMouseWheel(false);
for ind,frame in pairs(f.indicators) do
frame:Hide();
end
wipe(f.data);
f:SetAlpha(1);
f:Enable();
tinsert(mog.modelBin, f);
end
function mog:CreateCatalogueModel()
local f = mog:CreateModelFrame(mog.frame);
f.type = "catalogue";
f:SetScript("OnClick", f.OnClick);
f:SetScript("OnEnter", f.OnEnter);
f:SetScript("OnLeave", f.OnLeave);
tinsert(mog.models, f);
return f;
end
function mog:DeleteCatalogueModel(n)
mog:DeleteModelFrame(mog.models[n]);
tremove(mog.models, n);
end
function ModelFramePrototype:OnClick(button, ...)
if mog.active and mog.active.OnClick then
mog.active:OnClick(self, button, self.data.value, ...);
end
end
function ModelFramePrototype:OnEnter()
if mog.active and mog.active.OnEnter then
mog.active:OnEnter(self, self.data.value);
end
end
function ModelFramePrototype:OnLeave(...)
if mog.active and mog.active.OnLeave then
mog.active:OnLeave(self, self.data.value, ...);
else
GameTooltip:Hide();
end
end
function ModelFramePrototype:OnShow()
local lvl = self:GetParent():GetFrameLevel();
if self:GetFrameLevel() <= lvl then
self:SetFrameLevel(lvl+1);
end
self:ResetModel();
if self.type == "preview" then
self:Undress();
mog.DressFromPreview(self, self.parent);
else
if not self.data.value then
-- hack for models becoming visible OnShow, only do this if the frame is supposed to be hidden
self:SetAlpha(1)
self:SetAlpha(0)
end
mog:ModelUpdate(self, self.data.value);
end
end
function ModelFramePrototype:OnHide()
if mog.modelUpdater.model == self then
mog:StopModelUpdater();
end
self.model:SetPosition(0,0,0);
end
function ModelFramePrototype:OnUpdate()
--56, 108, 237, 238, 239, 243, 249, 250, 251, 252, 253, 254, 255
if mog.db.profile.noAnim then
self.model:SetSequence(3);
end
end
function ModelFramePrototype:OnDragStart(button)
mog:StartModelUpdater(self, button);
end
function ModelFramePrototype:OnDragStop(button)
mog:StopModelUpdater();
end
function ModelFramePrototype:ShowIndicator(name)
if not mog.indicators[name] then return end;
if not self.indicators[name] then
self.indicators[name] = mog.indicators[name](self.model);
end
self.indicators[name]:Show();
end
function ModelFramePrototype:SetText(text)
if not self.indicators.label then
self.indicators.label = mog.indicators.label(self.model);
end
self.indicators.label:SetText(text);
end
local tryOnSlots = {
MainHandSlot = "mainhand",
SecondaryHandSlot = "offhand",
}
function ModelFramePrototype:TryOn(item, slot)
self.model:TryOn(item, tryOnSlots[slot]);
end
function ModelFramePrototype:Undress()
self.model:Undress()
end
function ModelFramePrototype:UndressSlot(slot)
self.model:UndressSlot(slot)
end
function ModelFramePrototype:ApplyDress()
if mog.db.profile.gridDress == "equipped" then
self:ResetModel();
else
self:Undress();
if mog.db.profile.gridDress == "preview" then
mog.DressFromPreview(self, mog.activePreview);
end
end
end
function ModelFramePrototype:ResetModel()
local model = self.model;
model:SetPosition(0, 0, 0);
local info = self.type == "preview" and self.parent.data or mog;
-- :Dress resets the custom race, and :SetCustomRace does :Dress, so if we're using a custom race, just :SetCustomRace again instead of :Dress
if info.displayuseModel == myuseModel then
model:SetUnit("PLAYER");
model:Dress()
elseif UnitIsPlayer("TARGET") then
model:SetUnit("TARGET");
model:Dress();
end
self:PositionModel();
end
function ModelFramePrototype:PositionModel()
local model = self.model
if model:IsVisible() then
local sync = (mog.db.profile.sync or self.type == "catalogue");
local modelData = sync and mog or self.parent.data
model:SetPosition(modelData.posZ or 0, modelData.posX or 0, modelData.posY or 0);
model:SetFacing(modelData.face or 0);
end
end
function mog.DressFromPreview(model, previewFrame)
if not previewFrame then
return;
end
for id, slot in pairs(previewFrame.slots) do
if slot.item then
model:TryOn("item:" ..slot.item .. (previewFrame.data.weaponEnchant and ":" .. previewFrame.data.weaponEnchant or ""), slot.slot);
end
end
end
--//
--// Model Updater
mog.modelUpdater = CreateFrame("Frame",nil,UIParent);
mog.modelUpdater:Hide();
mog.modelUpdater:SetScript("OnUpdate",function(self,elapsed)
local cX,cY = GetCursorPosition();
local dX = (cX-self.pX)/50;
local dY = (cY-self.pY)/50;
if (mog.db.profile.sync or self.model.type == "catalogue") then
if self.btn == "LeftButton" then
mog.posZ = mog.posZ + dY;
mog.face = mog.face + dX;
elseif self.btn == "RightButton" then
mog.posX = mog.posX + dX;
mog.posY = mog.posY + dY;
end
for id,model in ipairs(mog.models) do
model:PositionModel();
end
if mog.db.profile.sync then
for id, preview in ipairs(mog.previews) do
preview.model:PositionModel();
end
end
else
local modelData = self.model.parent.data
if self.btn == "LeftButton" then
modelData.posZ = (modelData.posZ or mog.posZ or 0) + dY;
modelData.face = (modelData.face or mog.face or 0) + dX;
elseif self.btn == "RightButton" then
modelData.posX = (modelData.posX or mog.posX or 0) + dX;
modelData.posY = (modelData.posY or mog.posY or 0) + dY;
end
self.model:PositionModel();
end
self.pX,self.pY = cX,cY;
end);
function mog:StartModelUpdater(model, btn)
mog.modelUpdater.btn = btn;
mog.modelUpdater.model = model;
mog.modelUpdater.pX,mog.modelUpdater.pY = GetCursorPosition();
mog.modelUpdater:Show();
end
function mog:StopModelUpdater()
mog.modelUpdater:Hide();
mog.modelUpdater.btn = nil;
mog.modelUpdater.model = nil;
end
--//
--// Indicators
mog.indicators = {};
function mog:CreateIndicator(name,func)
if mog.indicators[name] then return end;
mog.indicators[name] = func;
end
--//
--// Scroll Frame
local updater = CreateFrame("Frame");
updater:Hide();
updater:SetScript("OnUpdate", function(self)
self:Hide();
mog:UpdateScroll();
mog.doModelUpdate = nil;
end);
mog.scroll = CreateFrame("Slider","MogItScroll",mog.frame,"UIPanelScrollBarTrimTemplate");
mog.scroll:Hide();
mog.scroll:SetPoint("TOPRIGHT",mog.frame.Inset,"TOPRIGHT",1,-17);
mog.scroll:SetPoint("BOTTOMRIGHT",mog.frame.Inset,"BOTTOMRIGHT",1,16);
mog.scroll:SetValueStep(1);
mog.scroll:SetScript("OnValueChanged",function(self,value,isUserInput)
if isUserInput then
self:SetValue(value);
value = self:GetValue();
end
self:update(nil,nil,value);
end);
mog.scroll.up = MogItScrollScrollUpButton;
mog.scroll.down = MogItScrollScrollDownButton;
mog.scroll.up:SetScript("OnClick",function(self)
mog.scroll:update(nil,-1);
end);
mog.scroll.down:SetScript("OnClick",function(self)
mog.scroll:update(nil,1);
end);
function mog.scroll.update(self, value, offset, onscroll)
local models = #mog.models;
local total = ceil(#mog.list/models);
if onscroll then
value = onscroll;
else
if total > 0 then
self:SetMinMaxValues(1, total);
end
if total > 1 then
self:Show();
else
self:Hide();
end
local old = self:GetValue();
value = (value or old or 1) + (offset or 0);
if value ~= old then
self:SetValue(value);
return;
end
end
if value == 1 then
self.up:Disable();
else
self.up:Enable();
end
if value == total then
self.down:Disable();
else
self.down:Enable();
end
if mog.Item_Menu:IsShown() or mog.Set_Menu:IsShown() then
HideDropDownMenu(1);
end
if mog.active and mog.active.OnScroll then
mog.active:OnScroll();
end
for id, frame in ipairs(mog.models) do
local index = ((value-1)*models)+id;
local value = mog.list[index];
wipe(frame.data);
if value then
frame.data.value = value;
frame.data.frame = frame;
frame.data.index = index;
for k, v in pairs(frame.indicators) do
v:Hide();
end
if frame:IsShown() then
mog:ModelUpdate(frame, value);
if GameTooltip:IsOwned(frame) then
frame:OnEnter();
end
else
frame:Show();
end
frame:SetAlpha(1);
frame:Enable();
else
if mog.modelUpdater.model == frame then
mog:StopModelUpdater();
end
frame:SetAlpha(0);
frame:Disable();
end
end
if total > 0 then
mog.frame.page:SetText(MERCHANT_PAGE_NUMBER:format(value, total));
mog.frame.page:Show();
else
mog.frame.page:Hide();
end
-- incorrect models may be tried on when items aren't cached, this queues another update if uncached items were found
if mog.doModelUpdate then
updater:Show();
end
end
mog.frame:SetScript("OnMouseWheel", function(self, offset)
mog.scroll:update(nil, offset > 0 and -1 or 1);
end);
function mog:UpdateScroll(value, offset)
mog.scroll:update(value, offset);
end
function mog:ModelUpdate(frame, value)
if mog.active and mog.active.FrameUpdate and value then
mog.active:FrameUpdate(frame, value);
end
end
--//
--// GUI
function mog:GetModelSize()
local x = floor((mog.db.profile.gridWidth+5-(4+10)-(10+18+4))/mog.db.profile.columns)-5;
local y = floor((mog.db.profile.gridHeight+5-(60+10)-(10+26))/mog.db.profile.rows)-5;
return x,y;
end
function mog:UpdateGUI(resize)
local profile = mog.db.profile;
local rows,columns = profile.rows,profile.columns;
local total = rows*columns;
local current = #mog.models;
local modelWidth,modelHeight = mog:GetModelSize();
if not resize then
if current > total then
for i=current,(total+1),-1 do
mog:DeleteCatalogueModel(i);
end
elseif current < total then
for i=(current+1),total,1 do
mog:CreateCatalogueModel();
end
end
mog.frame:SetPoint(profile.point, profile.x, profile.y);
mog.frame:SetSize(profile.gridWidth,profile.gridHeight);
if mog.frame:IsShown() then
mog.scroll:update();
end
end
for row=1,rows do
for column=1,columns do
local n = ((row-1)*columns)+column;
if not resize then
if n==1 then
mog.models[n]:SetPoint("TOPLEFT",mog.frame.Inset,"TOPLEFT",10,-10);
elseif column==1 then
mog.models[n]:SetPoint("TOPLEFT",mog.models[n-columns],"BOTTOMLEFT",0,-5);
else
mog.models[n]:SetPoint("TOPLEFT",mog.models[n-1],"TOPRIGHT",5,0);
end
end
mog.models[n]:SetSize(modelWidth,modelHeight);
end
end
end
--//
--// Toolbar
local function menuBarInitialize(self, level)
if self.active and self.active.func then
self.tier[level] = UIDROPDOWNMENU_MENU_VALUE;
self.active.func(self, level);
end
end
local function menuOnClick(self, btn)
if self.menuBar.active ~= self then
HideDropDownMenu(1);
end
self.menuBar.active = self;
if self.func then
self.menuBar:ToggleMenu(nil, self);
end
end
local function menuOnEnter(self)
if self.menuBar.active ~= self and self.menuBar:IsShown() then
HideDropDownMenu(1);
if self.func then
self.menuBar.active = self;
self.menuBar:ToggleMenu(nil, self);
end
end
self.nt:SetTexture(1,0.82,0,1);
end
local function menuOnLeave(self)
self.nt:SetTexture(0,0,0,0);
end
local function createMenu(menuBar, label, func)
local f = CreateFrame("Button", nil, menuBar.parent);
f:SetText(label);
f:SetNormalFontObject(GameFontNormal);
f:SetHighlightFontObject(GameFontBlack);
f:SetSize(f:GetFontString():GetStringWidth()+10, f:GetFontString():GetStringHeight()+10);
f.menuBar = menuBar
f.menuBar.xOffset = 0
f.menuBar.yOffset = 0
f.nt = f:CreateTexture(nil,"BACKGROUND");
--nt:SetTexture(0.8,0.3,0.8,1);
f.nt:SetTexture(0,0,0,0);
f.nt:SetAllPoints(f);
f:SetNormalTexture(f.nt);
f.func = func;
f:SetScript("OnClick",menuOnClick);
f:SetScript("OnEnter",menuOnEnter);
f:SetScript("OnLeave",menuOnLeave);
return f;
end
function mog.CreateMenuBar(parent)
local menuBar = mog:CreateDropdown("Menu");
menuBar.initialize = menuBarInitialize
menuBar.CreateMenu = createMenu;
menuBar.parent = parent
menuBar.tier = {};
return menuBar;
end
mog.menu = mog.CreateMenuBar(mog.frame);
--//
--// Module Menu
mog.menu.modules = mog.menu:CreateMenu(L["Modules"], function(self, tier)
if tier == 1 then
local info;
info = UIDropDownMenu_CreateInfo();
info.text = L["Base Modules"];
info.isTitle = true;
info.notCheckable = true;
info.justifyH = "CENTER";
UIDropDownMenu_AddButton(info,tier);
for k,v in ipairs(mog.moduleList) do
if v.base and v.Dropdown then
v:Dropdown(tier);
end
end
info = UIDropDownMenu_CreateInfo();
info.isTitle = true;
info.notCheckable = true;
UIDropDownMenu_AddButton(info,tier);
info = UIDropDownMenu_CreateInfo();
info.text = L["Extra Modules"];
info.isTitle = true;
info.notCheckable = true;
info.justifyH = "CENTER";
UIDropDownMenu_AddButton(info,tier);
for k,v in ipairs(mog.moduleList) do
if (not v.base) and v.Dropdown then
v:Dropdown(tier);
end
end
elseif self.tier[2] and self.tier[2].Dropdown then
self.tier[2]:Dropdown(tier);
end
end);
mog.menu.modules:SetPoint("TOPLEFT", mog.frame, "TOPLEFT", 62, -31);
--//
--// Catalogue Menu
local function setWeaponEnchant(self, enchant)
mog.weaponEnchant = enchant;
mog.menu:Rebuild(2);
mog.scroll:update();
end
local function setDisplayModel(self, arg1, value)
mog[arg1] = value;
for i, model in ipairs(mog.models) do
-- reset positions first since they tend to go nuts when manipulating the model
local modelData = model.parent.data
mog.posX = 0;
mog.posY = 0;
mog.posZ = 0;
model:ResetModel();
if model:IsEnabled() then
mog:ModelUpdate(model, model.data.value);
end
end
CloseDropDownMenus(1);
end
function mog:CreateuseModelMenu(dropdown, level, func, selecteduseModel)
for i = 0, 1 do
local info = UIDropDownMenu_CreateInfo();
info.text = useModel[i];
info.func = func;
info.checked = selecteduseModel == i;
info.arg1 = "displayuseModel";
info.arg2 = i;
dropdown:AddButton(info, level);
end
end
local dressOptions = {
none = NONE,
preview = L["Preview"],
equipped = L["Equipped"],
}
local function setGridDress(self)
mog.db.profile.gridDress = self.value;
for i, model in ipairs(mog.models) do
model.model:SetPosition(0, 0, 0)
end
mog.scroll:update();
for i, model in ipairs(mog.models) do
model:PositionModel()
end
CloseDropDownMenus(1);
end
function mog:ToggleFilters()
if not mog.filt:IsShown() then mog.filt:Show() else mog.filt:Hide() end
--mog.filt:SetShown(not mog.filt:IsShown());
end
mog.sorting = {};
mog.menu.catalogue = mog.menu:CreateMenu(L["Catalogue"], function(self, tier)
if tier == 1 then
local info = UIDropDownMenu_CreateInfo();
info.text = mog.filt:IsShown() and L["Hide Filters"] or L["Show Filters"];
info.notCheckable = true;
info.func = mog.ToggleFilters;
UIDropDownMenu_AddButton(info,tier);
local info = UIDropDownMenu_CreateInfo();
info.text = L["Sorting"];
info.value = "sorting";
info.notCheckable = true;
info.hasArrow = true;
info.disabled = not (mog.active and mog.active.sorting and #mog.active.sorting > 0);
UIDropDownMenu_AddButton(info,tier);
local info = UIDropDownMenu_CreateInfo();
info.text = "Use Model";
info.value = "useModel";
info.notCheckable = true;
info.hasArrow = true;
UIDropDownMenu_AddButton(info,tier);
local info = UIDropDownMenu_CreateInfo();
info.text = L["Dress models"];
info.value = "gridDress";
info.notCheckable = true;
info.hasArrow = true;
UIDropDownMenu_AddButton(info,tier);
local info = UIDropDownMenu_CreateInfo();
info.text = L["Weapon enchant"];
info.value = "weaponEnchant";
info.notCheckable = true;
info.hasArrow = true;
UIDropDownMenu_AddButton(info,tier);
elseif self.tier[2] == "sorting" then
if tier == 2 then
if mog.active and mog.active.sorting then
for k,v in ipairs(mog.active.sorting) do
if mog.sorting[v] and mog.sorting[v].Dropdown then
mog.sorting[v].Dropdown(self,mog.active,tier);
end
end
end
elseif self.tier[3] and self.tier[3].Dropdown then
self.tier[3].Dropdown(mog.active,tier);
end
elseif self.tier[2] == "useModel" then
mog:CreateuseModelMenu(self, tier, setDisplayModel, mog.displayuseModel)
elseif self.tier[2] == "weaponEnchant" then
if tier == 2 then
local info = UIDropDownMenu_CreateInfo();
info.text = NONE;
info.func = setWeaponEnchant;
info.arg1 = nil;
info.checked = mog.weaponEnchant == nil;
info.keepShownOnClick = true;
self:AddButton(info, tier);
for i, enchantCategory in ipairs(mog.enchants) do
local info = UIDropDownMenu_CreateInfo();
info.text = enchantCategory.name;
info.value = enchantCategory;
info.notCheckable = true;
info.hasArrow = true;
info.keepShownOnClick = true;
self:AddButton(info, tier);
end
elseif tier == 3 then
for i, enchant in ipairs(self.tier[3]) do
local info = UIDropDownMenu_CreateInfo();
info.text = enchant.name;
info.func = setWeaponEnchant;
info.arg1 = enchant.id;
info.checked = mog.weaponEnchant == enchant.id;
info.keepShownOnClick = true;
self:AddButton(info, tier);
end
end
elseif self.tier[2] == "gridDress" then
if tier == 2 then
for k, v in pairs(dressOptions) do
local info = UIDropDownMenu_CreateInfo();
info.text = v;
info.value = k;
info.func = setGridDress;
info.checked = mog.db.profile.gridDress == k;
info.keepShownOnClick = true;
self:AddButton(info,tier);
end
end
end
end);
mog.menu.catalogue:SetPoint("LEFT", mog.menu.modules, "RIGHT", 5, 0);
--//
--// Preview Menu
local function newPreview()
mog:CreatePreview();
ShowUIPanel(mog.view);
end
local function syncPreviews()
mog.db.profile.sync = not mog.db.profile.sync;
end
mog.menu.preview = mog.menu:CreateMenu(L["Preview"], function(self, tier)
if not mog.db.profile.singlePreview then
local info = UIDropDownMenu_CreateInfo();
info.text = L["New Preview"];
info.notCheckable = true;
info.func = newPreview;
UIDropDownMenu_AddButton(info,tier);
end
local info = UIDropDownMenu_CreateInfo();
info.text = mog.view:IsShown() and L["Hide Previews"] or L["Show Previews"];
info.notCheckable = true;
info.func = mog.TogglePreview;
UIDropDownMenu_AddButton(info,tier);
local info = UIDropDownMenu_CreateInfo();
info.text = L["Synchronize Positioning"];
info.checked = mog.db.profile.sync;
info.func = syncPreviews;
info.isNotRadio = true;
UIDropDownMenu_AddButton(info,tier);
end);
mog.menu.preview:SetPoint("LEFT", mog.menu.catalogue, "RIGHT", 5, 0);
--//
--// Options Menu
function mog:ToggleOptions()
if not mog.options then
mog.createOptions();
end
InterfaceOptionsFrame_OpenToCategory(MogIt);
end
mog.menu.options = mog.menu:CreateMenu(L["Options"]);
mog.menu.options:SetScript("OnClick", mog.ToggleOptions);
mog.menu.options:SetPoint("LEFT", mog.menu.preview, "RIGHT", 5, 0);
--//
local help = mog.menu:CreateMenu(L["Help"])
-- help:SetNormalFontObject(GameFontHighlight)
help:SetPoint("LEFT", mog.menu.options, "RIGHT", 5, 0)
help:SetScript("OnClick", nil);
help:SetScript("OnEnter", function(self)
GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")
GameTooltip:AddLine(L["How to use"]);
GameTooltip:AddLine(" ");
GameTooltip:AddLine(L["Model controls"]);
GameTooltip:AddLine(L["Left click and drag horizontally to rotate"], 1, 1, 1);
GameTooltip:AddLine(L["Left click and drag vertically to zoom"], 1, 1, 1);
GameTooltip:AddLine(L["Right click and drag to move"], 1, 1, 1);
local info = mog.active and mog.active.Help
if info then
GameTooltip:AddLine(" ");
GameTooltip:AddLine(L["Module controls"]);
for i, v in ipairs(info) do
GameTooltip:AddLine(v, 1, 1, 1);
end
end
GameTooltip:AddLine(" ");
GameTooltip:AddLine("Alt + Mouseover item = GameTooltip");
GameTooltip:Show()
self.nt:SetTexture(1, 0.82, 0, 1);
end);
help:SetScript("OnLeave", function(self)
GameTooltip_Hide()
self.nt:SetTexture(0, 0, 0, 0);
end);
--// Default Indicators
mog:CreateIndicator("label", function(model)
local label = model:CreateFontString(nil, "OVERLAY", "GameFontNormalMed3");
label:SetPoint("TOPLEFT", 12, -12);
label:SetPoint("BOTTOMRIGHT", -12, 12);
label:SetJustifyV("BOTTOM");
label:SetJustifyH("CENTER");
label:SetNonSpaceWrap(true);
return label;
end)
mog:CreateIndicator("hasItem", function(model)
local hasItem = model:CreateTexture(nil, "OVERLAY");
hasItem:SetTexture("Interface\\RaidFrame\\ReadyCheck-Ready");
hasItem:SetSize(32, 32);
hasItem:SetPoint("BOTTOMRIGHT", -8, 8);
return hasItem;
end)
mog:CreateIndicator("wishlist", function(model)
local wishlist = model:CreateTexture(nil, "OVERLAY");
wishlist:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcon_1");
wishlist:SetSize(32, 32);
wishlist:SetPoint("TOPRIGHT", -8, -8);
return wishlist;
end)
--//

99
MogIt/Core/Links.lua Normal file
View File

@@ -0,0 +1,99 @@
local MogIt,mog = ...;
local L = mog.L;
local charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
local base = #charset;
local maxlen = 3;
local function toBase(num)
local str;
if num <= 0 then
str = "0";
else
str = "";
while num > 0 do
str = charset:sub((num%base)+1,(num%base)+1)..str;
num = math.floor(num/base);
end
end
return str;
end
local function fromBase(str)
local num = 0;
for i=1,#str do
num = num + ((charset:find(str:sub(i,i))-1) * base^(#str-i));
end
return num;
end
function mog:SetToLink(set,enchant)
local link = "[MogIt:";
for k,v in pairs(set) do
link = link..("%0"..maxlen.."s"):format(toBase(v));
end
link = link..":";
link = link..(enchant and toBase(enchant) or 0);
link = link.."]";
return link;
end
function mog:LinkToSet(link)
local set = {};
--local items = link:match("MogIt:([^%]:]+)");
local items,enchant = link:match("MogIt:(%w*):?(%w*)");
if items then
for i=1,#items/maxlen do
table.insert(set,fromBase(items:sub((i-1)*maxlen+1,i*maxlen)));
end
end
enchant = enchant ~= "" and fromBase(enchant) or nil;
return set,enchant;
end
local function filter(self,event,msg,...)
msg = msg:gsub("%[(MogIt[^%]]+)%]","|cFFCC99FF|H%1|h[MogIt]|h|r");
return false, msg, ...;
end
ChatFrame_AddMessageEventFilter("CHAT_MSG_SAY",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_YELL",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_EMOTE",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_GUILD",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_OFFICER",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY_LEADER",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_RAID",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_RAID_LEADER",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_RAID_WARNING",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_BATTLEGROUND",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_BATTLEGROUND_LEADER",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_WHISPER",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_WHISPER_INFORM",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_CONVERSATION",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_INLINE_TOAST_BROADCAST",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_INLINE_TOAST_BROADCAST_INFORM",filter);
ChatFrame_AddMessageEventFilter("CHAT_MSG_CHANNEL",filter);
local SetHyperlink = ItemRefTooltip.SetHyperlink;
function ItemRefTooltip:SetHyperlink(link)
if link:find("^MogIt") then
if IsModifiedClick("CHATLINK") then
ChatEdit_InsertLink("["..link.."]")
else
local preview = mog:GetPreview();
local set,enchant = mog:LinkToSet(link);
--if race and gender then
if enchant then
preview.data.weaponEnchant = enchant
preview.model:ResetModel();
preview.model:Undress();
end
mog:AddToPreview(set,preview);
end
else
SetHyperlink(self, link);
end
end

325
MogIt/Core/Options.lua Normal file
View File

@@ -0,0 +1,325 @@
local MogIt,mog = ...;
local L = mog.L;
local LBR = LibStub("LibBabble-Race-3.0"):GetUnstrictLookupTable();
function mog.createOptions()
local about = LibStub("LibAddonInfo-1.0"):CreateFrame(MogIt,nil,"Interface\\AddOns\\MogIt\\Images");
local config = LibStub("AceConfig-3.0");
local dialog = LibStub("AceConfigDialog-3.0");
local db = LibStub("AceDBOptions-3.0");
local function get(info)
if info.arg == "minimap" then
return mog.db.profile.minimap.hide;
else
return mog.db.profile[info.arg];
end
end
local function set(info,value)
if info.arg == "minimap" then
mog.db.profile.minimap.hide = value;
if value then
mog.LDBI:Hide("MogIt");
else
mog.LDBI:Show("MogIt");
end
else
mog.db.profile[info.arg] = value;
if info.arg == "tooltipRotate" then
mog.tooltip.rotate:SetShown(value);
elseif info.arg == "sortWishlist" then
mog:BuildList(nil, "Wishlist");
elseif info.arg == "singlePreview" then
mog:SetSinglePreview(value);
elseif info.arg == "previewUIPanel" then
mog:SetPreviewUIPanel(value);
-- elseif info.arg == "previewFixedSize" then
-- mog:SetPreviewFixedSize(value);
elseif info.arg == "tooltipWidth" then
mog.tooltip:SetWidth(value);
elseif info.arg == "tooltipHeight" then
mog.tooltip:SetHeight(value);
elseif info.arg == "rows" or info.arg == "columns" then
mog:UpdateGUI();
end
end
end
local options = {
type = "group",
name = MogIt,
args = {},
};
options.args.general = {
type = "group",
order = 1,
name = GENERAL,
get = get,
set = set,
args = {
minimap = {
type = "toggle",
order = 1,
name = L["Hide minimap button"],
width = "full",
arg = "minimap",
},
sortWishlist = {
type = "toggle",
order = 1.3,
name = L["Sort wishlist sets alphabetically"],
width = "full",
arg = "sortWishlist",
},
dressupPreview = {
type = "toggle",
order = 1.4,
name = L["Use preview frame to dress up"],
width = "full",
arg = "dressupPreview",
},
singlePreview = {
type = "toggle",
order = 1.5,
name = L["Use a single preview frame"],
width = "full",
arg = "singlePreview",
confirm = function()
return L["This will close all your currently open previews."];
end,
},
previewUIPanel = {
type = "toggle",
order = 1.75,
name = L["Preview frame UI panel behaviour"],
width = "full",
arg = "previewUIPanel",
disabled = function()
return not mog.db.profile.singlePreview;
end,
},
--[[previewFixedSize = {
type = "toggle",
order = 1.8,
name = L["Preview frame fixed size"],
width = "full",
arg = "previewFixedSize",
disabled = function()
return not (mog.db.profile.singlePreview and mog.db.profile.previewUIPanel);
end,
},]]--
catalogue = {
type = "group",
order = 2,
name = L["Catalogue"],
inline = true,
args = {
noAnim = {
type = "toggle",
order = 1,
name = L["No animation"],
width = "double",
arg = "noAnim",
},
url = {
type = "select",
order = 2.5,
name = L["URL website"],
values = function()
local tbl = {};
for k,v in pairs(mog.url) do
tbl[k] = (v.fav and "\124T"..v.fav..":16\124t " or "")..k;
end
return tbl;
end,
arg = "url",
},
rows = {
type = "range",
order = 4,
name = L["Rows"],
step = 1,
min = 1,
max = 10,
arg = "rows",
},
columns = {
type = "range",
order = 5,
name = L["Columns"],
step = 1,
min = 1,
max = 15,
arg = "columns",
},
},
},
},
};
config:RegisterOptionsTable("MogIt_General",options.args.general);
dialog:AddToBlizOptions("MogIt_General",options.args.general.name,MogIt);
options.args.tooltip = {
type = "group",
order = 1,
name = L["Tooltip"],
get = get,
set = set,
args = {
tooltip = {
type = "toggle",
order = 1,
name = L["Enable tooltip model"],
width = "double",
arg = "tooltip",
},
dress = {
type = "toggle",
order = 2,
name = L["Dress model"],
width = "double",
arg = "tooltipDress",
},
mouse = {
type = "toggle",
order = 3,
name = L["Rotate with mouse wheel"],
width = "double",
arg = "tooltipMouse",
},
rotate = {
type = "toggle",
order = 4,
name = L["Auto rotate"],
width = "full",
arg = "tooltipRotate",
},
width = {
type = "range",
order = 5,
name = L["Width"],
step = 1,
min = 100,
max = 500,
arg = "tooltipWidth",
},
height = {
type = "range",
order = 6,
name = L["Height"],
step = 1,
min = 100,
max = 500,
arg = "tooltipHeight",
},
--[[ mog = {
type = "toggle",
order = 7,
name = L["Only transmogrification items"],
width = "double",
arg = "tooltipMog",
},]]--
modifier = {
type = "select",
order = 8,
name = L["Only show if modifier is pressed"],
values = function()
local tbl = {
None = "None",
};
for k,v in pairs(mog.tooltip.mod) do
tbl[k] = k;
end
return tbl;
end,
arg = "tooltipMod",
},
-- Custom race on tooltip models custom races broken throughout
--[[ customModel = {
type = "toggle",
order = 9,
name = L["Use custom model"],
width = "full",
arg = "tooltipCustomModel",
},
race = {
type = "select",
order = 10,
name = L["Model race"],
values = {
[1] = LBR["Human"],
[3] = LBR["Dwarf"],
[4] = LBR["Night Elf"],
[7] = LBR["Gnome"],
[11] = LBR["Draenei"],
[22] = LBR["Worgen"],
[2] = LBR["Orc"],
[5] = LBR["Undead"],
[6] = LBR["Tauren"],
[8] = LBR["Troll"],
[10] = LBR["Blood Elf"],
[9] = LBR["Goblin"],
[24] = LBR["Pandaren"],
},
arg = "tooltipRace",
disabled = function()
return not mog.db.profile.tooltipCustomModel;
end,
},
gender = {
type = "select",
order = 11,
name = L["Model gender"],
values = {
[0] = MALE,
[1] = FEMALE,
},
arg = "tooltipGender",
disabled = function()
return not mog.db.profile.tooltipCustomModel;
end,
}, --]]
},
};
config:RegisterOptionsTable("MogIt_Tooltip",options.args.tooltip);
dialog:AddToBlizOptions("MogIt_Tooltip",options.args.tooltip.name,MogIt);
--[[options.args.modules = {
type = "group",
order = 2,
name = L["Modules"],
--plugins
args = {
wishlist = db:GetOptionsTable(mog.wishlist.db),
},
};
options.args.modules.args.wishlist.name = L["Wishlist"];
config:RegisterOptionsTable("MogIt_Modules",options.args.modules);
dialog:AddToBlizOptions("MogIt_Modules",options.args.modules.name,MogIt);--]]
options.args.options = db:GetOptionsTable(mog.db);
options.args.options.name = L["Options profile"];
options.args.options.order = 5;
config:RegisterOptionsTable("MogIt_Options",options.args.options);
dialog:AddToBlizOptions("MogIt_Options",options.args.options.name,MogIt);
options.args.wishlist = db:GetOptionsTable(mog.wishlist.db);
options.args.wishlist.name = L["Wishlist profile"];
options.args.wishlist.order = 6;
config:RegisterOptionsTable("MogIt_Wishlist",options.args.wishlist);
dialog:AddToBlizOptions("MogIt_Wishlist",options.args.wishlist.name,MogIt);
mog.options = options;
end
local hook = CreateFrame("Frame",nil,InterfaceOptionsFrame);
hook:SetScript("OnShow",function(self)
if not mog.options then
mog.createOptions();
end
self:SetScript("OnShow",nil);
end);

950
MogIt/Core/Preview.lua Normal file
View File

@@ -0,0 +1,950 @@
local MogIt,mog = ...;
local L = mog.L;
local LBI = LibStub("LibBabble-Inventory-3.0"):GetUnstrictLookupTable();
local TITANS_GRIP_SPELLID = 46917
mog.view = CreateFrame("Frame","MogItPreview",UIParent);
mog.view:SetAllPoints();
mog.view:SetScript("OnShow",function(self)
if #mog.previews == 0 then
mog:CreatePreview();
end
if mog.db.profile.singlePreview then
ShowUIPanel(mog.previews[1]);
end
end);
mog.view:SetScript("OnHide",function(self)
if mog.db.profile.singlePreview then
HideUIPanel(mog.previews[1]);
end
end);
tinsert(UISpecialFrames,"MogItPreview");
--ShowUIPanel(mog.view);
function mog:ActivatePreview(preview)
mog.activePreview = preview;
preview.Bg:SetTexture("Interface\\AddOns\\MogIt\\FrameGeneral\\UI-Background-Rock",true);
preview.Bg:SetVertexColor(0.8,0.3,0.8);
preview.activate:Disable();
for k,v in ipairs(mog.previews) do
if v ~= preview then
v.Bg:SetVertexColor(1,1,1);
v.activate:Enable();
end
end
if mog.db.profile.gridDress == "preview" then
mog.scroll:update();
end
end
--// Preview Functions
local function raiseAll(self, ...)
local newLevel = self:GetFrameLevel() + 1
for i = 1, select("#", ...) do
select(i, ...):SetFrameLevel(newLevel)
end
end
local function stopMovingOrSizing(self)
self:StopMovingOrSizing();
local frameProps = mog.db.profile.previewProps[self:GetID()];
frameProps.point, frameProps.x, frameProps.y = select(3, self:GetPoint());
end
local function resizeOnMouseDown(self)
local f = self:GetParent();
f:SetMinResize(335,385);
f:SetMaxResize(GetScreenWidth(),GetScreenHeight());
f:StartSizing();
end
local function resizeOnMouseUp(self)
if mog.db.profile.singlePreview and mog.db.profile.previewUIPanel and mog.db.profile.previewFixedSize then return end
local f = self:GetParent();
f:StopMovingOrSizing();
local frameProps = mog.db.profile.previewProps[f:GetID()];
frameProps.w, frameProps.h = f:GetSize();
-- anchors may change from resizing
if not (mog.db.profile.singlePreview and mog.db.profile.previewUIPanel) then
frameProps.point, frameProps.x, frameProps.y = select(3, f:GetPoint());
UpdateUIPanelPositions(f)
end
end
local function modelOnMouseWheel(self, v)
local delta = ((v > 0 and 0.6) or -0.6);
if mog.db.profile.sync then
mog.posZ = mog.posZ + delta;
for id,model in ipairs(mog.models) do
model:PositionModel();
end
for id,preview in ipairs(mog.previews) do
preview.model:PositionModel();
end
else
self.parent.data.posZ = (self.parent.data.posZ or mog.posZ or 0) + delta;
self:PositionModel();
end
end
local function slotTexture(f, slot, texture)
f.slots[slot].icon:SetTexture(texture or select(2,GetInventorySlotInfo(slot)));
end
local function slotOnEnter(self)
if self.item then
mog.ShowItemTooltip(self, self.item);
else
GameTooltip:SetOwner(self,"ANCHOR_RIGHT");
GameTooltip:SetText(_G[strupper(self.slot)]);
end
end
local function slotOnLeave(self)
GameTooltip:Hide();
end
local function slotOnClick(self,btn)
if btn == "RightButton" and IsControlKeyDown() then
local preview = self:GetParent();
mog.view.DelItem(self.slot,preview);
if mog.db.profile.gridDress == "preview" and mog.activePreview == preview then
mog.scroll:update();
end
slotOnEnter(self);
else
mog.Item_OnClick(self,btn,self);
end
end
local function previewOnClose(self)
if mog.db.profile.singlePreview then
mog.view:Hide();
elseif mog.db.profile.previewConfirmClose then
StaticPopup_Show("MOGIT_PREVIEW_CLOSE", nil, nil, self:GetParent());
else
mog:DeletePreview(self:GetParent());
end
end
local function previewActivate(self)
mog:ActivatePreview(self:GetParent());
end
--//
--// Preview Menu
local currentPreview;
local function setDisplayModel(self, arg1, value)
currentPreview.data[arg1] = value;
local model = currentPreview.model;
model:ResetModel();
model:Undress();
mog.DressFromPreview(model, currentPreview);
CloseDropDownMenus();
end
local function setWeaponEnchant(self, preview, enchant)
preview.data.weaponEnchant = enchant;
self.owner:Rebuild(2);
mog.scroll:update();
local mainHandItem = preview.slots["MainHandSlot"].item;
local offHandItem = preview.slots["SecondaryHandSlot"].item;
if mainHandItem then
preview.model:TryOn(format("item:%d:%d", mainHandItem, preview.data.weaponEnchant), "MainHandSlot");
end
if offHandItem then
preview.model:TryOn(format("item:%d:%d", offHandItem, preview.data.weaponEnchant), "SecondaryHandSlot");
end
end
local previewMenu = {
{
text = "Use Model",
value = "useModel",
notCheckable = true,
hasArrow = true,
},
{
text = L["Weapon enchant"],
value = "weaponEnchant",
notCheckable = true,
hasArrow = true,
},
{
text = L["Add Item"],
notCheckable = true,
func = function(self)
StaticPopup_Show("MOGIT_PREVIEW_ADDITEM", nil, nil, currentPreview);
end,
},
{
text = L["Chat Link"],
notCheckable = true,
func = function(self)
local tbl = {};
for k, v in pairs(currentPreview.slots) do
if v.item then
table.insert(tbl, v.item);
end
end
ChatEdit_InsertLink(mog:SetToLink(tbl, currentPreview.data.weaponEnchant));
--ChatFrame_OpenChat(link);
end,
},
{
text = L["Import / Export"],
notCheckable = true,
func = function(self)
StaticPopup_Show("MOGIT_PREVIEW_IMPORT", nil, nil, currentPreview);
end,
},
{
text = L["Equip current gear"],
notCheckable = true,
func = function(self)
for k, v in pairs(currentPreview.slots) do
mog.view.DelItem(k, currentPreview);
local slotID = GetInventorySlotInfo(k);
local item = GetInventoryItemID("player", slotID) --mog.mogSlots[slotID] and select(6, GetTransmogrifySlotInfo(slotID)) or
-- print(item)
if (k ~= "HeadSlot" or ShowingHelm()) and (k ~= "BackSlot" or ShowingCloak()) then
mog.view.AddItem(item, currentPreview);
end
end
if mog.activePreview == currentPreview and mog.db.profile.gridDress == "preview" then
mog.scroll:update();
end
end,
},
{
text = "Equip target's gear",
func = function(self)
for k, v in pairs(currentPreview.slots) do
mog.view.DelItem(k, currentPreview);
NotifyInspect("target")
local slotID = GetInventorySlotInfo(k);
local item = GetInventoryItemID("target", slotID) --mog.mogSlots[slotID] and select(6, GetTransmogrifySlotInfo(slotID)) or
-- print(item)
if (k ~= "HeadSlot" or ShowingHelm()) and (k ~= "BackSlot" or ShowingCloak()) then
mog.view.AddItem(item, currentPreview);
ClearInspectPlayer()
end
end
if mog.activePreview == currentPreview and mog.db.profile.gridDress == "preview" then
mog.scroll:update();
end
end,
},
{
text = L["Clear"],
notCheckable = true,
func = function(self)
mog.view:Undress(currentPreview);
if mog.activePreview == currentPreview and mog.db.profile.gridDress == "preview" then
mog.scroll:update();
end
end,
},
}
local function previewInitialize(self, level)
if level == 1 then
currentPreview = self.parent;
for i, info in ipairs(previewMenu) do
UIDropDownMenu_AddButton(info, level);
end
elseif self.tier[2] == "useModel" then
mog:CreateuseModelMenu(self, level, setDisplayModel, self.parent.data.displayuseModel)
elseif self.tier[2] == "weaponEnchant" then
if level == 2 then
local info = UIDropDownMenu_CreateInfo();
info.text = NONE;
info.func = setWeaponEnchant;
info.arg1 = self.parent;
info.arg2 = nil;
info.checked = self.parent.data.weaponEnchant == nil;
info.keepShownOnClick = true;
self:AddButton(info, level);
for i, enchantCategory in ipairs(mog.enchants) do
local info = UIDropDownMenu_CreateInfo();
info.text = enchantCategory.name;
info.value = enchantCategory;
info.notCheckable = true;
info.hasArrow = true;
info.keepShownOnClick = true;
self:AddButton(info, level);
end
elseif level == 3 then
for i, enchant in ipairs(self.tier[3]) do
local info = UIDropDownMenu_CreateInfo();
info.text = enchant.name;
info.func = setWeaponEnchant;
info.arg1 = self.parent;
info.arg2 = enchant.id;
info.checked = self.parent.data.weaponEnchant == enchant.id;
info.keepShownOnClick = true;
self:AddButton(info, level);
end
end
end
end
--//
--// Save Menu
local newSet = {items = {}}
local function onClick(self, set)
newSet.name = set
wipe(newSet.items)
for slot, v in pairs(currentPreview.slots) do
newSet.items[slot] = v.item
end
StaticPopup_Show("MOGIT_WISHLIST_OVERWRITE_SET", set, nil, newSet)
end
local function newSetOnClick(self)
wipe(newSet.items)
newSet.name = "Set "..(#mog.wishlist:GetSets() + 1)
for slot, v in pairs(currentPreview.slots) do
newSet.items[slot] = v.item
end
StaticPopup_Show("MOGIT_WISHLIST_CREATE_SET", nil, nil, newSet)
end
local function saveInitialize(self, level)
currentPreview = self.parent;
mog.wishlist:AddSetMenuItems(level, onClick)
local info = UIDropDownMenu_CreateInfo()
info.text = L["New set"]
info.func = newSetOnClick
info.colorCode = GREEN_FONT_COLOR_CODE
info.notCheckable = true
self:AddButton(info, level)
end
--//
--// Load Menu
local function onClick(self, set, profile)
mog.view:Undress(currentPreview);
mog:AddToPreview(mog.wishlist:GetSetItems(set, profile), currentPreview)
CloseDropDownMenus()
end
local function loadInitialize(self, level)
currentPreview = self.parent;
if level == 1 then
mog.wishlist:AddSetMenuItems(level, onClick)
local info = UIDropDownMenu_CreateInfo()
info.text = L["Other profiles"]
info.hasArrow = true
info.notCheckable = true
self:AddButton(info, level)
elseif level == 2 then
local curProfile = mog.wishlist:GetCurrentProfile()
for i, profile in ipairs(mog.wishlist:GetProfiles()) do
if profile ~= curProfile and mog.wishlist:GetSets(profile) then
local info = UIDropDownMenu_CreateInfo()
info.text = profile
info.hasArrow = true
info.notCheckable = true
self:AddButton(info, level)
end
end
elseif level == 3 then
mog.wishlist:AddSetMenuItems(level, onClick, UIDROPDOWNMENU_MENU_VALUE, UIDROPDOWNMENU_MENU_VALUE)
end
end;
--//
--// Toolbar
local function helpOnEnter(self)
self.nt:SetTexture(1,0.82,0,1);
GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT");
GameTooltip:AddLine(L["How to use"]);
GameTooltip:AddLine(" ");
GameTooltip:AddLine(L["Basic Controls"]);
GameTooltip:AddLine(L["Left click and drag horizontally to rotate"],1,1,1);
GameTooltip:AddLine(L["Left click and drag vertically to zoom"],1,1,1);
GameTooltip:AddLine(L["Right click and drag to move"],1,1,1);
GameTooltip:AddLine(L["Click the bottom right corner and drag to resize"],1,1,1);
GameTooltip:AddLine(L["Click the \"Activate\" button to set this as the active preview"],1,1,1);
GameTooltip:AddLine(" ");
GameTooltip:AddLine(L["Slot Controls"]);
GameTooltip:AddLine(L["Shift + Left click to link an item to chat"],1,1,1);
GameTooltip:AddLine(L["Ctrl + Left click to try on an item"],1,1,1);
GameTooltip:AddLine(L["Right click to show the item menu"],1,1,1);
GameTooltip:AddLine(L["Shift + Right click to show a URL for the item"],1,1,1);
GameTooltip:AddLine(L["Ctrl + Right click to remove the item from the preview"],1,1,1);
GameTooltip:Show();
end
local function helpOnLeave(self)
GameTooltip:Hide();
self.nt:SetTexture(0,0,0,0);
end
local function createMenuBar(parent)
local menuBar = mog.CreateMenuBar(parent)
menuBar.preview = menuBar:CreateMenu(L["Preview"], previewInitialize);
menuBar.preview:SetPoint("TOPLEFT", parent, 62, -31);
menuBar.load = menuBar:CreateMenu(L["Load"], loadInitialize);
menuBar.load:SetPoint("LEFT", menuBar.preview, "RIGHT", 5, 0);
menuBar.save = menuBar:CreateMenu(L["Save"], saveInitialize);
menuBar.save:SetPoint("LEFT", menuBar.load, "RIGHT", 5, 0);
menuBar.help = menuBar:CreateMenu(L["Help"]);
menuBar.help:SetPoint("LEFT", menuBar.save, "RIGHT", 5, 0);
menuBar.help:SetScript("OnEnter",helpOnEnter);
menuBar.help:SetScript("OnLeave",helpOnLeave);
end
--//
--// Preview Frame
local function initPreview(frame, id)
frame:SetID(id);
local props = mog.db.profile.previewProps[id];
frame:ClearAllPoints();
frame:SetPoint(props.point, props.x, props.y);
frame:SetSize(props.w, props.h);
frame.TitleText:SetText(L["Preview %d"]:format(id));
frame.data = {
displayuseModel = mog.playeruseModel,
};
end
mog.previews = {};
mog.previewBin = {};
mog.previewNum = 0;
function mog:CreatePreview()
if mog.previewBin[1] then
local f = mog.previewBin[1];
local leastIndex = #mog.previews + 1;
-- find the lowest unused frame ID
for i, v in ipairs(self.previewBin) do
leastIndex = min(v:GetID(), leastIndex);
end
initPreview(f, leastIndex);
f:Show();
mog:ActivatePreview(f);
tremove(mog.previewBin,1);
tinsert(mog.previews, f);
return f;
end
mog.previewNum = mog.previewNum + 1;
local id = mog.previewNum;
local f = CreateFrame("Frame", "MogItPreview"..id, mog.view, "ButtonFrameTemplate");
initPreview(f, id);
f:SetToplevel(true);
f:SetClampedToScreen(true);
f:EnableMouse(true);
f:SetMovable(true);
f:SetResizable(true);
f:Raise();
f.onCloseCallback = previewOnClose;
f.Bg = _G["MogItPreview"..id.."Bg"];
--f.Bg:SetVertexColor(0.8,0.3,0.8);
f.portrait:Hide();
f.portraitFrame:Hide();
f.topLeftCorner:Show();
f.topBorderBar:SetPoint("TOPLEFT", f.topLeftCorner, "TOPRIGHT", 0, 0);
f.leftBorderBar:SetPoint("TOPLEFT", f.topLeftCorner, "BOTTOMLEFT", 0, 0);
--ButtonFrameTemplate_HidePortrait(f);
f.resize = CreateFrame("Button", nil, f);
f.resize:SetSize(16, 16);
f.resize:SetPoint("BOTTOMRIGHT", -4, 3);
f.resize:EnableMouse(true);
f.resize:SetHitRectInsets(0, -4, 0, -3);
f.resize:SetScript("OnMouseDown", resizeOnMouseDown);
f.resize:SetScript("OnMouseUp", resizeOnMouseUp);
f.resize:SetScript("OnHide", resizeOnMouseUp);
f.resize:SetNormalTexture([[Interface\ChatFrame\UI-ChatIM-SizeGrabber-Up]]);
f.resize:SetPushedTexture([[Interface\ChatFrame\UI-ChatIM-SizeGrabber-Down]])
f.resize:SetHighlightTexture([[Interface\ChatFrame\UI-ChatIM-SizeGrabber-Highlight]])
f.slots = {};
for i, slotIndex in ipairs(mog.slots) do
local slot = CreateFrame("Button", "MogItCorePreviewSlot"..i, f, "ItemButtonTemplate");
slot.slot = slotIndex;
slot.icon = _G["MogItCorePreviewSlot"..i.."IconTexture"]
if i == 1 then
slot:SetPoint("TOPLEFT", f.Inset, "TOPLEFT", 8, -8);
elseif i == 8 then
slot:SetPoint("TOPRIGHT", f.Inset, "TOPRIGHT", -7, -8);
elseif i == 12 then
slot:SetPoint("TOP", f.slots[mog:GetSlot(i-1)], "BOTTOM", 0, -45);
else
slot:SetPoint("TOP", f.slots[mog:GetSlot(i-1)], "BOTTOM", 0, -4);
end
slot:RegisterForClicks("AnyUp");
slot:SetScript("OnClick", slotOnClick);
slot:SetScript("OnEnter", slotOnEnter);
slot:SetScript("OnLeave", slotOnLeave);
slot.OnEnter = slotOnEnter;
f.slots[slotIndex] = slot;
slotTexture(f, slotIndex);
end
f.model = mog:CreateModelFrame(f);
f.model.type = "preview";
f.model:Show();
f.model:EnableMouseWheel(true);
f.model:SetScript("OnMouseWheel", modelOnMouseWheel);
f.model:SetPoint("TOPLEFT", f.Inset, "TOPLEFT", 49, -8);
f.model:SetPoint("BOTTOMRIGHT", f.Inset, "BOTTOMRIGHT", -49, 8);
f.activate = CreateFrame("Button", "MogItPreview"..id.."Activate", f, "MagicButtonTemplate");
f.activate:SetText(L["Activate"]);
f.activate:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 5, 5);
f.activate:SetWidth(100);
f.activate:SetScript("OnClick", previewActivate);
f:SetScript("OnMouseDown", f.StartMoving);
f:SetScript("OnMouseUp", stopMovingOrSizing);
createMenuBar(f);
mog:ActivatePreview(f);
-- child frames occasionally appears behind the parent for whatever reason, so we raise them here
raiseAll(f, f:GetChildren())
tinsert(mog.previews, f);
return f;
end
function mog:DeletePreview(f)
HideUIPanel(f);
f:ClearAllPoints();
f:SetPoint("CENTER",mog.view,"CENTER");
mog.view:Undress(f);
wipe(f.data);
tinsert(mog.previewBin,f);
for k,v in ipairs(mog.previews) do
if v == f then
tremove(mog.previews,k);
break;
end
end
if mog.activePreview == f then
mog.activePreview = nil;
if mog.db.profile.gridDress == "preview" then
mog.scroll:update();
end
end
if #mog.previews == 0 then
HideUIPanel(mog.view);
end
end
function mog:GetPreview(frame)
if self.db.profile.singlePreview then
frame = self.previews[1];
end
return frame or self:CreatePreview();
end
function mog:SetSinglePreview(isSinglePreview)
for i = #mog.previews, 1, -1 do
mog:DeletePreview(mog.previews[i]);
end
if isSinglePreview then
-- hack to make sure CreatePreview gets the frame named MogItPreview1
if #mog.previewBin > 1 and mog.previewBin[1] ~= MogItPreview1 then
for i = 2, #mog.previewBin do
if mog.previewBin[i] == MogItPreview1 then
tremove(mog.previewBin, i);
tinsert(mog.previewBin, 1, MogItPreview1);
break;
end
end
end
mog:CreatePreview();
end
if MogItPreview1 then
mog:SetPreviewUIPanel(mog.db.profile.previewUIPanel);
end
mog:SetPreviewMenu(isSinglePreview);
end
function mog:SetPreviewUIPanel(isUIPanel)
if isUIPanel and mog.db.profile.singlePreview then
MogItPreview1:SetScript("OnMouseDown", nil);
MogItPreview1:SetScript("OnMouseUp", nil);
MogItPreview1:SetScript("OnHide", HideParentPanel);
UIPanelWindows["MogItPreview1"] = {
area = "left",
pushable = 1,
whileDead = true,
}
HideUIPanel(MogItPreview1);
else
local props = mog.db.profile.previewProps[1];
local point, x, y = props.point, props.x, props.y;
HideUIPanel(MogItPreview1);
MogItPreview1:SetScript("OnMouseDown", MogItPreview1.StartMoving);
MogItPreview1:SetScript("OnMouseUp", stopMovingOrSizing);
MogItPreview1:SetScript("OnHide", nil);
UIPanelWindows["MogItPreview1"] = nil;
MogItPreview1:SetAttribute("UIPanelLayout-defined", nil);
MogItPreview1:ClearAllPoints();
MogItPreview1:SetPoint(point, x, y);
end
mog:SetPreviewFixedSize(mog.db.profile.previewFixedSize);
end
function mog:SetPreviewFixedSize(isFixedSize)
local isUIPanel = mog.db.profile.previewUIPanel;
if isFixedSize and isUIPanel then
MogItPreview1:SetSize(PANEL_DEFAULT_WIDTH, PANEL_DEFAULT_HEIGHT);
else
local props = mog.db.profile.previewProps[1];
MogItPreview1:SetSize(props.w, props.h);
end
if not (isUIPanel and isFixedSize) then MogItPreview1.resize:Show() else MogItPreview1.resize:Hide() end
--MogItPreview1.resize:SetShown(not ());
UpdateUIPanelPositions(MogItPreview1);
end
local cachedPreviews;
local doCache = {};
mog:AddItemCacheCallback("PreviewAddItem", function()
cachedPreviews = {};
for i = #doCache, 1, -1 do
local item = doCache[i]
if GetItemInfo(item.id) then
cachedPreviews[item.frame] = true;
mog.view.AddItem(item.id, item.frame);
tremove(doCache, i)
end
end
-- update the grid if using preview grid dress, and an item was cached on the active preview
if mog.db.profile.gridDress == "preview" and cachedPreviews[mog.activePreview] then
mog:UpdateScroll();
end
end)
local function additem(item, preview, forceSlot, subType, invType, texture)
local slot = mog:GetSlot(invType)
if type(forceSlot) == "string" then
slot = forceSlot
end
if slot then
if slot == "MainHandSlot" or slot == "SecondaryHandSlot" then
if invType == "INVTYPE_2HWEAPON" then
if IsSpellKnown(TITANS_GRIP_SPELLID) then
-- Titan's Grip exists in the spellbook, so we can treat this weapon as one handed
invType = "INVTYPE_WEAPON";
end
end
if invType == "INVTYPE_WEAPON" then
-- put one handed weapons in the off hand if: main hand is occupied, off hand is free and a two handed weapon isn't equipped
if preview.slots["MainHandSlot"].item and not preview.slots["SecondaryHandSlot"].item and not preview.data.twohand then
slot = "SecondaryHandSlot";
end
end
if invType == "INVTYPE_2HWEAPON" or invType == "INVTYPE_RANGED" or (invType == "INVTYPE_RANGEDRIGHT" and subType ~= LBI["Wands"]) then
-- if any two handed weapon is being equipped, first clear up both hands
mog.view.DelItem("MainHandSlot", preview);
mog.view.DelItem("SecondaryHandSlot", preview);
preview.data.twohand = true;
elseif preview.data.twohand then
preview.data.twohand = false;
if slot == "MainHandSlot" then
mog.view.DelItem("SecondaryHandSlot", preview);
elseif slot == "SecondaryHandSlot" then
mog.view.DelItem("MainHandSlot", preview);
end
end
end
preview.slots[slot].item = item;
slotTexture(preview, slot, texture);
if preview:IsVisible() then
if (slot == "MainHandSlot" or slot == "SecondaryHandSlot") and preview.data.weaponEnchant then
item = format("item:%d:%d", item, preview.data.weaponEnchant)
end
if invType == "INVTYPE_RANGED" then
slot = "SecondaryHandSlot"
end
preview.model:TryOn(item, slot);
end
end
end
local delay = CreateFrame("GameTooltip", "mogitGT", nil, "GameTooltipTemplate")
function mog.view.AddItem(item, preview, forceSlot)
if not (item and preview) then return end;
local subType,_,invType,texture = select(7,GetItemInfo(item));
if not invType then
delay:SetHyperlink('|Hitem:'..item..'|h')
delay:SetScript("OnUpdate",function()
subType,_,invType,texture = select(7,GetItemInfo(item));
additem(item, preview, forceSlot, subType,invType,texture)
delay:SetScript("OnUpdate",nil)
end)
return;
else additem(item, preview, forceSlot, subType,invType,texture)
end
end
function mog.view.DelItem(slot,preview)
if not (preview and slot and preview.slots[slot].item) then return end;
local item = preview.slots[slot].item
preview.slots[slot].item = nil;
slotTexture(preview,slot);
if preview:IsVisible() then
local invType = (select(9,GetItemInfo(item)))
if invType == "INVTYPE_RANGED" then slot = "SecondaryHandSlot" end
--preview.model:UndressSlot(GetInventorySlotInfo(slot));
--mog.view:Undress(preview);
preview.model:Undress()
for k,v in pairs(preview.slots) do
mog.view.AddItem(v.item,preview,k);
end
end
end
function mog:AddToPreview(item,preview)
if not item then return end;
preview = mog:GetPreview(preview or mog.activePreview);
ShowUIPanel(mog.view);
if type(item) == "number" then
mog.view.AddItem(item,preview);
elseif type(item) == "string" then
mog.view.AddItem(tonumber(item:match("item:(%d+)")),preview);
elseif type(item) == "table" then
--mog.view:Undress(preview);
preview.model:Undress()
for k,v in pairs(item) do
mog.view.AddItem(v,preview,k);
end
end
if mog.db.profile.gridDress == "preview" and mog.activePreview == preview then
mog.scroll:update();
end
return preview;
end
function mog.view:Undress(preview)
for k, v in pairs(preview.slots) do
mog.view.DelItem(k, preview);
end
end
--//
--// Hooks
if not ModifiedItemClickHandlers then
ModifiedItemClickHandlers = {};
local origHandleModifiedItemClick = HandleModifiedItemClick;
function HandleModifiedItemClick(link)
if not link then
return false;
end
for i, v in ipairs(ModifiedItemClickHandlers) do
if v(link) then
return true;
end
end
return origHandleModifiedItemClick(link);
end
end
-- hack to allow post hooking SetItemRef for previewing
tinsert(ModifiedItemClickHandlers, function(link)
local button = GetMouseButtonClicked()
if button then
if link and IsDressableItem(link) then
if IsModifiedClick("DRESSUP") then
return DressUpItemLink(link);
elseif IsControlKeyDown() and button == "RightButton" then
mog:AddToPreview(link);
return true;
end
end
elseif IsModifiedClick("DRESSUP") then
-- if no mouse button was detected, this happened through a chat link
-- if it's a dressup modified click and a dressable item, intercept the call here and let SetItemRef hook handle it
return link and IsDressableItem(link);
end
local _, staticPopup = StaticPopup_Visible("MOGIT_PREVIEW_ADDITEM");
if IsModifiedClick("CHATLINK") and staticPopup then
staticPopup.editBox:SetText(link);
return true
end
end);
hooksecurefunc("SetItemRef", function(link, text, button, chatFrame)
local id = tonumber(link:match("^item:(%d+)"));
if link:match("item:%d+") and IsModifiedClick("DRESSUP") then
if button == "RightButton" then
mog:AddToPreview(link);
else
DressUpItemLink(link);
end
end
end)
local origDressUpItemLink = DressUpItemLink;
function DressUpItemLink(link)
if not (link and IsDressableItem(link)) then
return false;
end
if mog.db.profile.dressupPreview then
mog:AddToPreview(link);
return true;
end
return origDressUpItemLink(link);
end
local function hookInspectUI()
local function onClick(self, button)
if InspectFrame.unit and self.hasItem and IsControlKeyDown() and button == "RightButton" then
-- GetInventoryItemID actually returns the transmogged-into item for inspect units
mog:AddToPreview(GetInventoryItemID(InspectFrame.unit, self:GetID()));
else
HandleModifiedItemClick(GetInventoryItemLink(InspectFrame.unit, self:GetID()));
end
end
for k, v in ipairs(mog.slots) do
_G["Inspect"..v]:RegisterForClicks("AnyUp");
_G["Inspect"..v]:SetScript("OnClick", onClick);
end
hookInspectUI = nil;
end
if InspectFrame then
hookInspectUI();
else
mog.view:SetScript("OnEvent",function(self,event,addon)
if addon == "Blizzard_InspectUI" then
hookInspectUI();
self:UnregisterEvent(event);
self:SetScript("OnEvent", nil);
end
end);
mog.view:RegisterEvent("ADDON_LOADED");
end
--//
--// Popups
local function onAccept(self,preview)
local text = self.editBox:GetText();
text = text and text:match("(%d+).-$");
mog:AddToPreview(tonumber(text),preview);
end
StaticPopupDialogs["MOGIT_PREVIEW_ADDITEM"] = {
text = L["Type the item ID or url in the text box below"],
button1 = ADD,
button2 = CANCEL,
hasEditBox = 1,
maxLetters = 512,
editBoxWidth = 260,
OnAccept = onAccept,
EditBoxOnEnterPressed = function(self, data)
local parent = self:GetParent();
onAccept(parent, data);
parent:Hide();
end,
EditBoxOnEscapePressed = function(self)
self:GetParent():Hide();
end,
timeout = 0,
exclusive = 1,
whileDead = 1,
};
local function onAccept(self,preview)
local items = self.editBox:GetText();
items = items and items:match("compare%?items=([^;#]+)");
if items then
local tbl = {};
for item in items:gmatch("([^:]+)") do
item = item:match("^(%d+)");
table.insert(tbl,tonumber(item));
end
mog:AddToPreview(tbl,preview);
end
end
StaticPopupDialogs["MOGIT_PREVIEW_IMPORT"] = {
text = L["Copy and paste a Wowhead Compare URL into the text box below to import"],
button1 = L["Import"],
button2 = CANCEL,
hasEditBox = 1,
maxLetters = 512,
editBoxWidth = 260,
OnShow = function(self,preview)
local str;
for k,v in pairs(preview.slots) do
if v.item then
if str then
str = str..":"..v.item;
else
str = L["http://www.wowhead.com/"].."compare?items="..v.item;
end
end
end
self.editBox:SetText(str or "");
self.editBox:HighlightText();
end,
OnAccept = onAccept,
EditBoxOnEnterPressed = function(self, data)
local parent = self:GetParent();
onAccept(parent, data);
parent:Hide();
end,
EditBoxOnEscapePressed = function(self)
self:GetParent():Hide();
end,
timeout = 0,
exclusive = 1,
whileDead = 1,
};
StaticPopupDialogs["MOGIT_PREVIEW_CLOSE"] = {
text = L["Are you sure you want to close this set?"],
button1 = YES,
button2 = NO,
OnAccept = function(self, frame)
mog:DeletePreview(frame);
end,
hideOnEscape = true,
whileDead = true,
timeout = 0,
}

View File

@@ -0,0 +1,32 @@
local MogIt, mog = ...;
local L = mog.L;
mog.sorting = {};
function mog:CreateSort(name, data)
data = data or {};
data.name = name;
mog.sorting[name] = data;
end
function mog:GetSort(name)
return mog.sorting[name];
end
function mog:GetActiveSort()
return mog.sorting.active;
end
function mog:SortList(new, update)
if mog.active and mog.active.sorting and #mog.active.sorting > 0 then
new = new or (mog.active.sorts[mog.sorting.active] and mog.sorting.active) or mog.active.sorting[1];
if mog.sorting.active and (mog.sorting.active ~= new) and mog.sorting[mog.sorting.active].Unlist then
mog.sorting[mog.sorting.active].Unlist();
end
mog.sorting.active = new;
mog.sorting[new].Sort(mog.active.sorts[new]);
if not update then
mog.scroll:update();
end
end
end

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Ui xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.blizzard.com/wow/ui/" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="Sorting.lua"/>
<Script file="level.lua"/>
<Script file="itemLevel.lua"/>
<Script file="display.lua"/>
<Script file="id.lua"/>
<Script file="colour.lua"/>
</Ui>

View File

@@ -0,0 +1,63 @@
local MogIt,mog = ...;
local L = mog.L;
local colourCache = {};
local cR,cG,cB = 255,255,255;
local function colourScore(id,args)
if not colourCache[id] then
local distance = 195075;
local colours = args and args(id);
if colours then
for k,v in pairs(colours) do
local r,g,b = v:match("^(..)(..)(..)$");
r = tonumber(r,16);
g = tonumber(g,16);
b = tonumber(b,16);
local dist = ((cR-r)^2)+((cG-g)^2)+((cB-b)^2);
if dist < distance then
distance = dist;
end
end
end
colourCache[id] = distance;
end
return colourCache[id];
end
local function dropdownTier1(self)
mog:SortList("colour");
end
local function swatchFunc()
if not ColorPickerFrame:IsShown() then
local r,g,b = ColorPickerFrame:GetColorRGB();
cR,cG,cB = r*255,g*255,b*255;
mog:SortList("colour");
end
end
mog:CreateSort("colour",{
label = L["Approximate Colour"],
Dropdown = function(dropdown,module,tier)
local info = UIDropDownMenu_CreateInfo();
info.text = L["Approximate Colour"];
info.value = "colour";
info.func = dropdownTier1;
info.checked = mog.sorting.active == "colour";
info.hasColorSwatch = true;
info.r = cR/255;
info.g = cG/255;
info.b = cB/255;
info.swatchFunc = swatchFunc;
dropdown:AddButton(info,tier);
end,
Sort = function(args)
wipe(colourCache);
table.sort(mog.list,function(a,b)
return colourScore(a,args) < colourScore(b,args);
end);
end,
Unlist = function()
wipe(colourCache);
end,
});

View File

@@ -0,0 +1,25 @@
local MogIt,mog = ...;
local L = mog.L;
local function dropdownTier1(self)
mog:SortList("display");
end
local function displayIDSort(a, b)
return mog:GetData("item", a[1], "display") > mog:GetData("item", b[1], "display");
end
mog:CreateSort("display",{
label = L["Display ID"],
Dropdown = function(dropdown,module,tier)
local info = UIDropDownMenu_CreateInfo();
info.text = L["Display ID"];
info.value = "display";
info.func = dropdownTier1;
info.checked = mog.sorting.active == "display";
dropdown:AddButton(info,tier);
end,
Sort = function(args)
table.sort(mog.list, displayIDSort);
end,
});

25
MogIt/Core/Sorting/id.lua Normal file
View File

@@ -0,0 +1,25 @@
local MogIt,mog = ...;
local L = mog.L;
local function dropdownTier1(self)
mog:SortList("id");
end
local function displayIDSort(a, b)
return mog:GetData("item", a[1], "id") > mog:GetData("item", b[1], "id");
end
mog:CreateSort("id",{
label = L["Item ID"],
Dropdown = function(dropdown,module,tier)
local info = UIDropDownMenu_CreateInfo();
info.text = L["Item ID"];
info.value = "id";
info.func = dropdownTier1;
info.checked = mog.sorting.active == "id";
dropdown:AddButton(info,tier);
end,
Sort = function(args)
table.sort(mog.list, displayIDSort);
end,
});

View File

@@ -0,0 +1,25 @@
local MogIt,mog = ...;
local L = mog.L;
local function dropdownTier1(self)
mog:SortList("itemLevel");
end
local function itemLevelSort(a, b)
return mog:GetData("item", a[1], "itemLevel") > mog:GetData("item", b[1], "itemLevel");
end
mog:CreateSort("itemLevel",{
label = L["Item Level"],
Dropdown = function(dropdown,module,tier)
local info = UIDropDownMenu_CreateInfo();
info.text = L["Item Level"];
info.value = "itemLevel";
info.func = dropdownTier1;
info.checked = mog.sorting.active == "itemLevel";
dropdown:AddButton(info,tier);
end,
Sort = function(args)
table.sort(mog.list, itemLevelSort);
end,
});

View File

@@ -0,0 +1,45 @@
local MogIt, mog = ...;
local L = mog.L;
local itemCache = {};
local function minItem(items)
local minLevel
for i, v in ipairs(items) do
local reqLevel = itemCache[v] or mog:GetData("item", v, "level");
if reqLevel then
itemCache[v] = reqLevel;
minLevel = min(reqLevel, minLevel or reqLevel);
end
end
return minLevel or 0;
end
local function dropdownTier1(self)
mog:SortList("level");
end
local function levelSort(a, b)
local aLv, bLv = minItem(a), minItem(b);
if aLv == bLv then
return mog:GetData("item", a[1], "id") > mog:GetData("item", b[1], "id");
else
return aLv > bLv;
end
end
mog:CreateSort("level", {
label = LEVEL,
Dropdown = function(dropdown,module,tier)
local info;
info = UIDropDownMenu_CreateInfo();
info.text = LEVEL;
info.value = "level";
info.func = dropdownTier1;
info.checked = mog.sorting.active == "level";
dropdown:AddButton(info, tier);
end,
Sort = function()
table.sort(mog.list, levelSort);
end,
});

564
MogIt/Core/Templates.lua Normal file
View File

@@ -0,0 +1,564 @@
local MogIt, mog = ...
local L = mog.L
local TEXTURE = [[Interface\RaidFrame\ReadyCheck-Ready]]
local function getTexture(hasItem, embedded)
local texture = hasItem and TEXTURE or ""
return embedded and format("|T%s:0|t ", texture) or texture
end
local itemQualityColor = {
[0] = "9d9d9d",
[1] = "ffffff",
[2] = "1eff00",
[3] = "0070dd",
[4] = "a335ee",
[5] = "ff8000",
[6] = "e6cc80",
[7] = "e6cc80"
}
function mog:GetItemLabel(itemID, callback, includeIcon, iconSize)
local name,_,quality = GetItemInfo(itemID)
local itemname = mog:GetData("item", itemID, "itemname")
local itemquality = mog:GetData("item", itemID, "quality")
local includeIcon = GetItemIcon(itemID)
-- Uncached items will revert to local database and show an asterisk next to them. Non-existent items will not show an icon.
-- GetItemInfo requires the item to be in the cache. GetItemIcon does not.
return (includeIcon and "|T"..GetItemIcon(itemID)..":"..(iconSize or "32") .."|t" or "")..
(name and "|cff"..itemQualityColor[quality].." "..name .."|r" or itemname and "|cff"..itemQualityColor[itemquality].." "..itemname .."|r"..RED_FONT_COLOR_CODE.."*" )
end
local function addTooltipDoubleLine(textLeft, textRight)
GameTooltip:AddDoubleLine(textLeft, textRight, nil, nil, nil, 1, 1, 1)
end
local function addItemTooltipLine(itemID)
addTooltipDoubleLine(getTexture(mog:HasItem(itemID), true)..mog:GetItemLabel(itemID, "ModelOnEnter"), mog.GetItemSourceShort(itemID))
end
function mog.GetItemSourceInfo(itemID)
local source, info;
local sourceType = mog:GetData("item", itemID, "source");
local sourceID = mog:GetData("item", itemID, "sourceid");
local sourceInfo = mog:GetData("item", itemID, "sourceinfo");
if sourceType == 1 and sourceID then -- Drop
source = mog:GetData("npc", sourceID, "name");
-- IsQuestFlaggedCompleted is a MoP API. WotLK has GetQuestsCompleted which returns all quests (option?)
-- elseif sourceType == 3 and sourceID then -- Quest
-- info = IsQuestFlaggedCompleted(sourceID) or false;
-- info = false
elseif sourceType == 5 and sourceInfo then -- Crafted
source = L.professions[sourceInfo];
elseif sourceType == 6 and sourceID then -- Achievement
local _, name, _, complete = GetAchievementInfo(sourceID);
source = name;
info = complete;
end
local zone = mog:GetData("item", itemID, "zone");
if zone then
--zone = GetMapNameByID(zone);
SetMapByID(zone)
zone = GetMapInfo()
SetMapByID(GetCurrentMapAreaID())
if zone then
local diff = L.diffs[sourceInfo];
if sourceType == 1 and diff then
zone = format("%s (%s)", zone, diff);
end
end
end
return L.source[sourceType], source, zone, info;
end
function mog.GetItemSourceShort(itemID)
local sourceType, source, zone, info = mog.GetItemSourceInfo(itemID);
if zone then
if source then
sourceType = source;
end
source = zone;
if sourceType == L.source[3] then
source = format("%s (%s)", source, sourceType)
end
end
return source or sourceType
end
-- create a new set and add the item to it
local function previewOnClick(self, previewFrame)
mog:AddToPreview(self.value, mog:GetPreview(previewFrame))
CloseDropDownMenus()
end
-- create a new set and add the item to it
local function newSetOnClick(self)
StaticPopup_Show("MOGIT_WISHLIST_CREATE_SET", nil, nil, self.value)
CloseDropDownMenus()
end
local previewItem = {
text = L["Preview"],
-- hasArrow = true,
menuList = function(level)
local info = UIDropDownMenu_CreateInfo()
info.text = L["Active preview"]
info.value = UIDROPDOWNMENU_MENU_VALUE
info.func = previewOnClick
info.disabled = not mog.activePreview
info.notCheckable = true
info.arg1 = mog.activePreview
UIDropDownMenu_AddButton(info, level)
for i, preview in ipairs(mog.previews) do
local info = UIDropDownMenu_CreateInfo()
info.text = format("%s %d", L["Preview"], preview:GetID())
info.value = UIDROPDOWNMENU_MENU_VALUE
info.func = previewOnClick
info.notCheckable = true
info.arg1 = preview
UIDropDownMenu_AddButton(info, level)
end
local info = UIDropDownMenu_CreateInfo()
info.text = L["New preview"]
info.value = UIDROPDOWNMENU_MENU_VALUE
info.func = previewOnClick
info.notCheckable = true
UIDropDownMenu_AddButton(info, level)
end,
}
local itemOptionsMenu = {
previewItem,
{
text = L["Add to wishlist"],
func = function(self)
mog.wishlist:AddItem(self.value)
mog:BuildList()
CloseDropDownMenus()
end,
},
{
text = L["Add to set"],
hasArrow = true,
menuList = function(level)
mog.wishlist:AddSetMenuItems(level, "addItem", UIDROPDOWNMENU_MENU_VALUE)
local info = UIDropDownMenu_CreateInfo()
info.text = L["New set"]
info.value = UIDROPDOWNMENU_MENU_VALUE
info.func = newSetOnClick
info.colorCode = GREEN_FONT_COLOR_CODE
info.notCheckable = true
UIDropDownMenu_AddButton(info, level)
end,
},
{
wishlist = true,
text = L["Delete"],
func = function(self, set)
mog.wishlist:DeleteItem(self.value, set.name)
mog:BuildList(nil, "Wishlist")
CloseDropDownMenus()
end,
},
}
function mog:SetPreviewMenu(isSinglePreview)
if isSinglePreview then
previewItem.func = previewOnClick
previewItem.hasArrow = nil
else
previewItem.func = nil
previewItem.hasArrow = true
end
end
function mog:AddItemOption(info)
tinsert(itemOptionsMenu, info)
end
local function createItemMenu(dropdown, data, func)
local items = data.items
-- not listing the items if it's only 1 and it's not a set
if not items or (data.item and #items == 1) then
return
end
local isArray = #items > 0
for i, v in ipairs(isArray and items or mog.slots) do
v = isArray and v or items[v]
if v then
local info = UIDropDownMenu_CreateInfo()
info.text = mog:GetItemLabel(v, func and "ItemMenu" or "SetMenu")
info.value = v
info.func = func
info.checked = (i == data.cycle)
info.hasArrow = true
info.notCheckable = data.isSaved or data.name
info.arg1 = data
info.arg2 = i
info.menuList = itemOptionsMenu
dropdown:AddButton(info)
end
end
return true
end
local function createMenu(self, level, menuList)
local data = self.data
if type(menuList) == "function" then
menuList(level)
else
for i, info in ipairs(menuList) do
if (info.wishlist == nil or info.wishlist == data.isSaved) and (not info.set or data.items) then
info.value = UIDROPDOWNMENU_MENU_VALUE
info.notCheckable = true
info.arg1 = data
self:AddButton(info, level)
end
end
end
end
local slots = {
[1] = "MainHandSlot",
-- [2] = "mainhand",
-- [3] = "offhand",
}
function mog.Item_FrameUpdate(self, data)
self:ApplyDress()
self:TryOn(("item:".. data.item.. (mog.weaponEnchant and ":"..mog.weaponEnchant or "")), slots[mog:GetData("item", data.item, "slot")])
end
local sourceLabels = {
[L.source[1]] = BOSS,
}
GameTooltip:RegisterEvent("MODIFIER_STATE_CHANGED")
GameTooltip:HookScript("OnEvent", function(self, event, key, state)
local owner = self:GetOwner()
if owner and self[mog] then
owner:OnEnter()
end
end)
GameTooltip:HookScript("OnTooltipCleared", function(self)
self[mog] = nil
end)
local class_HEXcolors = {
["HUNTER"] = "ffabd473",
["WARLOCK"] = "ff9482c9",
["PRIEST"] = "ffffffff",
["PALADIN"] = "fff58cba",
["MAGE"] = "ff69ccf0",
["ROGUE"] = "fffff569",
["DRUID"] = "ffff7d0a",
["SHAMAN"] = "ff0070de",
["WARRIOR"] = "ffc79c6e",
["DEATHKNIGHT"] = "ffc41f3b",
}
function mog.ShowItemTooltip(self, item, items, cycle)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip[mog] = true
local l
if IsAltKeyDown() then
GameTooltip:SetHyperlink('|Hitem:'..item..'|h')
l = true
if cycle and #items > 1 then GameTooltip:AddLine(" ") GameTooltip:AddDoubleLine("", L["Item %d/%d"]:format(cycle, #items), nil, nil, nil, 1, 0, 0) end
end
if not l then
-- Reverts to local database if item isn't cached
local itemLevel = (select(4,GetItemInfo(item))) or mog:GetData("item", item, "itemlevel")
local itemLabel = mog:GetItemLabel(item, "ModelOnEnter")
if cycle and #items > 1 then
GameTooltip:AddDoubleLine(itemLabel, L["Item %d/%d"]:format(cycle, #items), nil, nil, nil, 1, 0, 0)
else
GameTooltip:AddLine(itemLabel)
end
local bindType = mog:GetData("item", item, "bind")
if bindType then
addTooltipDoubleLine(L["Bind"]..":", L.bind[bindType])
end
-- Can't use GetItemInfo on LevelReq due to many quest items not having one
local requiredLevel = mog:GetData("item", item, "level")
if requiredLevel then
addTooltipDoubleLine(LEVEL..":", requiredLevel)
end
addTooltipDoubleLine("Item level:", itemLevel)
local faction = mog:GetData("item", item, "faction")
if faction then
addTooltipDoubleLine(FACTION..":", (faction == 1 and FACTION_ALLIANCE or FACTION_HORDE))
end
local class = mog:GetData("item", item, "class")
if class and class > 0 then
local str
for k, v in pairs(L.classBits) do
if bit.band(class, v) > 0 then
local color = class_HEXcolors[k]
local name = LOCALIZED_CLASS_NAMES_MALE[k]
if color and name then
if str then
str = format("%s, |c%s%s|r", str, color, name)
else
str = format("|c%s%s|r", color, name)
end
else print("Error: MogIt\Core\Template.lua:316 ", color,name )
end
end
end
addTooltipDoubleLine(CLASS..":", str)
end
local slot = mog:GetData("item", item, "slot")
if slot then
addTooltipDoubleLine(L["Slot"]..":", L.slots[slot])
end
end
GameTooltip:AddLine(" ")
local sourceType, source, zone, info = mog.GetItemSourceInfo(item)
if sourceType then
addTooltipDoubleLine(L["Source"]..":", sourceType)
if source then
addTooltipDoubleLine((sourceLabels[sourceType] or sourceType)..":", source)
end
if info ~= nil then
addTooltipDoubleLine(STATUS..":", info and COMPLETE or INCOMPLETE)
end
end
if zone then
addTooltipDoubleLine(ZONE..":", zone)
end
GameTooltip:AddLine(" ")
addTooltipDoubleLine(ID..":", item)
if mog:HasItem(item) then
GameTooltip:AddLine(" ")
GameTooltip:AddLine(L["You have this item."], 1, 1, 1)
GameTooltip:AddTexture(TEXTURE)
end
if (not mog.active or mog.active.name ~= "Wishlist") and mog.wishlist:IsItemInWishlist(item) then
if not mog:HasItem(item) then
GameTooltip:AddLine(" ")
end
GameTooltip:AddLine(L["This item is on your wishlist."], 1, 1, 1)
GameTooltip:AddTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcon_1")
end
if items and #items > 1 then
GameTooltip:AddLine(" ")
GameTooltip:AddLine(L["Other items using this appearance:"])
for i, v in ipairs(items) do
if v ~= item then
addItemTooltipLine(v)
end
end
end
if l and AtlasLoot then
if AtlasLoot.db.profile.SearchOn.All then
AtlasLoot_LoadAllModules();
else
for k, v in pairs(AtlasLoot.db.profile.SearchOn) do
if k ~= "All" and v == true and not IsAddOnLoaded(k) and LoadAddOn(k) and self.db.profile.LoDNotify then
--DEFAULT_CHAT_FRAME:AddMessage(GREEN..AL["AtlasLoot"]..": "..ORANGE..k..WHITE.." "..AL["sucessfully loaded."]);
end
end
end
for dataID, data in pairs(AtlasLoot_Data) do
for _, v in ipairs(data) do
local id = v[2]
if item == id then
local a = AtlasLoot_TableNames[dataID] and AtlasLoot_TableNames[dataID][1] or "Argh!"
GameTooltip:AddLine(" ");
GameTooltip:AddDoubleLine("|cff6578ffAtlasLoot: |cffffff00"..a, dataID, nil, nil, nil, 1, 1, 1);
end
end
end
end
GameTooltip:Show()
end
local function showMenu(menu, data, isSaved)
if menu:IsShown() and menu.data ~= data then
HideDropDownMenu(1)
end
-- needs to be either true or false
data.isSaved = isSaved ~= nil
menu.data = data
menu:Toggle(data.item, "cursor")
end
function mog.Item_OnClick(self, btn, data, isSaved)
local item = data.item
if not (self and item) then return end
if btn == "LeftButton" then
if (not HandleModifiedItemClick(select(2, GetItemInfo(item))) or IsAltKeyDown()) and data.items then
data.cycle = (data.cycle % #data.items) + 1
data.item = data.items[data.cycle]
self:OnEnter()
end
elseif btn == "RightButton" then
if IsControlKeyDown() then
mog:AddToPreview(item)
elseif IsShiftKeyDown() then
mog:ShowURL(item)
else
showMenu(mog.Item_Menu, data, isSaved)
end
end
end
do
local function itemOnClick(self, data, index)
data.cycle = index
data.item = data.items[index]
end
mog.Item_Menu = mog:CreateDropdown("Menu")
mog.Item_Menu.initialize = function(self, level, menuList)
local data = self.data
if not menuList then
if not createItemMenu(self, data, itemOnClick) then
-- this is a single item, so skip directly to the item options menu
createMenu(self, level, itemOptionsMenu)
end
return
end
createMenu(self, level, menuList)
end
end
function mog.Set_FrameUpdate(self, data)
self:ShowIndicator("label")
self:SetText(data.name)
self:Undress()
for k, v in pairs(data.items) do
self:TryOn(v, k)
end
end
function mog.ShowSetTooltip(self, items, name)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip[mog] = true
GameTooltip:AddLine(name)
for i, slot in ipairs(mog.slots) do
local itemID = items[slot] or items[i]
if itemID then
addItemTooltipLine(itemID)
end
end
GameTooltip:Show()
end
function mog.Set_OnClick(self, btn, data, isSaved)
if btn == "LeftButton" then
if IsShiftKeyDown() then
ChatEdit_InsertLink(mog:SetToLink(data.items))
elseif IsControlKeyDown() then
if mog.db.profile.dressupPreview then
mog:AddToPreview(data.items, mog:GetPreview())
else
if not DressUpFrame:IsShown() or DressUpFrame.mode ~= "player" then
DressUpFrame.mode = "player"
-- DressUpFrame.ResetButton:Show()
local race, fileName = UnitRace("player")
SetDressUpBackground(DressUpFrame, fileName)
ShowUIPanel(DressUpFrame)
DressUpModel:SetUnit("player")
end
DressUpModel:Undress()
for k, v in pairs(data.items) do
DressUpItemLink(v)
end
end
end
elseif btn == "RightButton" then
if IsShiftKeyDown() then
if data.set then
mog:ShowURL(data.set, "set")
else
mog:ShowURL(data.items, "compare")
end
elseif IsControlKeyDown() then
mog:AddToPreview(data.items, mog:GetPreview())
else
showMenu(mog.Set_Menu, data, isSaved)
end
end
end
do
local setMenu = {
{
wishlist = false,
text = L["Add set to wishlist"],
func = function(self, set, items)
local create = mog.wishlist:CreateSet(set)
if create then
for i, itemID in pairs(items) do
mog.wishlist:AddItem(itemID, set)
end
end
end,
},
{
wishlist = true,
text = L["Rename set"],
func = function(self, set)
mog.wishlist:RenameSet(set)
end,
},
{
wishlist = true,
text = L["Delete set"],
func = function(self, set)
mog.wishlist:DeleteSet(set)
end,
},
}
function mog:AddSetOption(info)
tinsert(setMenu, info)
end
mog.Set_Menu = mog:CreateDropdown("Menu")
mog.Set_Menu.initialize = function(self, level, menuList)
local data = self.data
if not menuList then
createItemMenu(self, data)
for i, info in ipairs(setMenu) do
if info.wishlist == nil or info.wishlist == data.isSaved then
info.value = data.name
info.notCheckable = true
info.arg1 = data.name
info.arg2 = data.items
self:AddButton(info, level)
end
end
return
end
createMenu(self, level, menuList)
end
end

215
MogIt/Core/Tooltip.lua Normal file
View File

@@ -0,0 +1,215 @@
local MogIt,mog = ...;
local L = mog.L;
local IsDressableItem = IsDressableItem;
local GetScreenWidth = GetScreenWidth;
local GetScreenHeight = GetScreenHeight;
local class = L.classBits[select(2,UnitClass("PLAYER"))];
--// Tooltip
mog.tooltip = CreateFrame("Frame","MogItTooltip",UIParent,"TooltipBorderedFrameTemplate");
mog.tooltip:Hide();
mog.tooltip:SetClampedToScreen(true);
mog.tooltip:SetFrameStrata("TOOLTIP");
mog.tooltip:SetScript("OnShow",function(self)
if mog.db.profile.tooltipMouse and not InCombatLockdown() then
SetOverrideBinding(mog.tooltip,true,"MOUSEWHEELUP","MogIt_TooltipScrollUp");
SetOverrideBinding(mog.tooltip,true,"MOUSEWHEELDOWN","MogIt_TooltipScrollDown");
end
end);
mog.tooltip:SetScript("OnHide",function(self)
if not InCombatLockdown() then
ClearOverrideBindings(mog.tooltip);
end
end);
mog.tooltip:SetScript("OnEvent", function(self, event, arg1)
if event == "PLAYER_LOGIN" then
mog.tooltip.model:SetUnit("player");
elseif event == "PLAYER_REGEN_DISABLED" then
ClearOverrideBindings(mog.tooltip);
elseif event == "PLAYER_REGEN_ENABLED" then
if self:IsShown() and mog.db.profile.tooltipMouse then
SetOverrideBinding(mog.tooltip,true,"MOUSEWHEELUP","MogIt_TooltipScrollUp");
SetOverrideBinding(mog.tooltip,true,"MOUSEWHEELDOWN","MogIt_TooltipScrollDown");
end
end
end);
mog.tooltip:RegisterEvent("PLAYER_LOGIN");
mog.tooltip:RegisterEvent("PLAYER_REGEN_DISABLED");
mog.tooltip:RegisterEvent("PLAYER_REGEN_ENABLED");
--//
--// Model
mog.tooltip.model = CreateFrame("DressUpModel",nil,mog.tooltip);
mog.tooltip.model:SetPoint("TOPLEFT",mog.tooltip,"TOPLEFT",5,-5);
mog.tooltip.model:SetPoint("BOTTOMRIGHT",mog.tooltip,"BOTTOMRIGHT",-5,5);
mog.tooltip.model:SetScript("OnShow",function(self)
--[[
if mog.db.profile.tooltipCustomModel then
self:SetCustomRace(mog.db.profile.tooltipRace, mog.db.profile.tooltipGender);
-- hack for hidden helm and cloak showing on models
local showingHelm, showingCloak = ShowingHelm(), ShowingCloak();
local helm, cloak = GetInventoryItemID("player", INVSLOT_HEAD), GetInventoryItemID("player", INVSLOT_BACK);
if not showingHelm and helm then
self:TryOn(helm);
self:UndressSlot(INVSLOT_HEAD);
end
if not showingCloak and cloak then
self:TryOn(cloak);
self:UndressSlot(INVSLOT_BACK);
end
self:RefreshCamera();
else
self:Dress();
end
--]]
self:Dress();
if not mog.db.profile.tooltipDress then
self:Undress();
end
end);
function mog.tooltip.ShowItem(self)
local _,itemLink = self:GetItem();
if not itemLink then
return;
end
local itemID = tonumber(itemLink:match("item:(%d+)"));
local db = mog.db.profile
local tooltip = mog.tooltip
if db.tooltip and (not tooltip.mod[db.tooltipMod] or tooltip.mod[db.tooltipMod]()) then
if not self[mog] then
if tooltip.item ~= itemLink then
tooltip.item = itemLink;
local token = mog.tokens[itemID];
if token then
for item, classBit in pairs(token) do
if bit.band(class, classBit) > 0 then
itemLink = item;
break;
end
end
end
local slot = select(9,GetItemInfo(itemLink));
if (not db.tooltipMog ) and tooltip.slots[slot] and IsDressableItem(itemLink) then
tooltip.model:SetFacing(tooltip.slots[slot]-(db.tooltipRotate and 0.5 or 0));
tooltip:Show();
tooltip.owner = self;
--if mog.global.tooltipAnchor then
tooltip.repos:Show();
--else
-- tooltip:ClearAllPoints();
-- tooltip:SetPoint("BOTTOMRIGHT","UIParent","BOTTOMRIGHT",-CONTAINER_OFFSET_X - 13,CONTAINER_OFFSET_Y);
--end
tooltip.model:TryOn(itemLink);
else
tooltip:Hide();
end
end
else
-- tooltip:Hide();
end
end
-- add wishlist info about this item
if not self[mog] and mog.wishlist:IsItemInWishlist(itemID) then
self:AddLine(" ");
self:AddLine(L["This item is on your wishlist."], 1, 1, 0);
self:AddTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcon_1");
end
end
function mog.tooltip.HideItem(self)
mog.tooltip.check:Show();
end
--//
--// GameTooltip
mog.tooltip.check = CreateFrame("Frame");
mog.tooltip.check:Hide();
mog.tooltip.check:SetScript("OnUpdate",function(self)
if (mog.tooltip.owner and not (mog.tooltip.owner:IsShown() and mog.tooltip.owner:GetItem())) or not mog.tooltip.owner then
mog.tooltip:Hide();
mog.tooltip.item = nil;
end
self:Hide();
end);
mog.tooltip.repos = CreateFrame("Frame");
mog.tooltip.repos:Hide();
mog.tooltip.repos:SetScript("OnUpdate",function(self)
local x,y = mog.tooltip.owner:GetCenter();
if x and y then
mog.tooltip:ClearAllPoints();
local mogpoint,ownerpoint;
if y/GetScreenHeight() > 0.5 then
mogpoint = "TOP";
ownerpoint = "BOTTOM";
else
mogpoint = "BOTTOM";
ownerpoint = "TOP";
end
if x/GetScreenWidth() > 0.5 then
mogpoint = mogpoint.."LEFT";
ownerpoint = ownerpoint.."LEFT";
else
mogpoint = mogpoint.."RIGHT";
ownerpoint = ownerpoint.."RIGHT";
end
mog.tooltip:SetPoint(mogpoint,mog.tooltip.owner,ownerpoint);
self:Hide();
end
end);
GameTooltip:HookScript("OnTooltipSetItem",mog.tooltip.ShowItem);
GameTooltip:HookScript("OnHide",mog.tooltip.HideItem);
--//
--// Auto-Rotate
mog.tooltip.rotate = CreateFrame("Frame",nil,mog.tooltip);
mog.tooltip.rotate:Hide();
mog.tooltip.rotate:SetScript("OnUpdate",function(self,elapsed)
mog.tooltip.model:SetFacing(mog.tooltip.model:GetFacing() + elapsed);
end);
--//
--// Tables
mog.tooltip.slots = {
INVTYPE_HEAD = 0,
INVTYPE_SHOULDER = 0,
INVTYPE_CLOAK = 3.4,
INVTYPE_CHEST = 0,
INVTYPE_ROBE = 0,
INVTYPE_WRIST = 0,
INVTYPE_2HWEAPON = 1.6,
INVTYPE_WEAPON = 1.6,
INVTYPE_WEAPONMAINHAND = 1.6,
INVTYPE_WEAPONOFFHAND = -0.7,
INVTYPE_SHIELD = -0.7,
INVTYPE_HOLDABLE = -0.7,
INVTYPE_RANGED = 1.6,
INVTYPE_RANGEDRIGHT = 1.6,
INVTYPE_THROWN = 1.6,
INVTYPE_HAND = 0,
INVTYPE_WAIST = 0,
INVTYPE_LEGS = 0,
INVTYPE_FEET = 0,
};
mog.tooltip.mod = {
Shift = IsShiftKeyDown,
Ctrl = IsControlKeyDown,
Alt = IsAltKeyDown,
};
--//

161
MogIt/Core/URL.lua Normal file
View File

@@ -0,0 +1,161 @@
local MogIt,mog = ...;
local L = mog.L;
mog.url = {};
function mog:AddURL(name,tbl)
mog.url[name] = tbl;
end
function mog:ShowURL(id,sub,url,force)
if not id then return end;
url = url or mog.db.profile.url;
sub = sub or "item";
if not (force or (mog.url[url] and mog.url[url][sub])) then
url = "Wowhead";
end
if mog.url[url] and mog.url[url][sub] then
local text;
if type(mog.url[url][sub]) == "function" then
text = mog.url[url][sub](id);
else
text = mog.url[url][sub]:format(id);
end
if text then
StaticPopup_Show("MOGIT_URL",mog.url[url].fav and "\124T"..mog.url[url].fav..":18:18\124t " or "",url,text);
return true;
end
end
end
StaticPopupDialogs["MOGIT_URL"] = {
preferredIndex = 3,
text = "%s%s "..L["URL"],
button1 = CLOSE,
hasEditBox = 1,
maxLetters = 512,
hasWideEditBox = 1,
OnShow = function(self,url)
self.wideEditBox:SetText(url);
self.wideEditBox:SetFocus();
self.wideEditBox:HighlightText();
end,
EditBoxOnEnterPressed = function(self)
self:GetParent():Hide();
end,
EditBoxOnEscapePressed = function(self)
self:GetParent():Hide();
end,
timeout = 0,
exclusive = 1,
whileDead = 1,
hideOnEscape = 1
};
mog:AddURL("Wowhead",{
fav = "Interface\\AddOns\\MogIt\\Images\\fav_wh",
item = L["http://www.wowhead.com/"].."item=%d",
set = L["http://www.wowhead.com/"].."itemset=%d",
npc = L["http://www.wowhead.com/"].."npc=%d",
spell = L["http://www.wowhead.com/"].."spell=%d",
compare = function(tbl)
local str;
for k,v in pairs(tbl) do
if str then
str = str..":"..v;
else
str = L["http://www.wowhead.com/"].."compare?items="..v;
end
end
return str;
end,
});
mog:AddURL("WOWDB",{
fav = "Interface\\AddOns\\MogIt\\Images\\fav_mmo",
item = "http://www.wowdb.com/items/%d",
set = "http://www.wowdb.com/item-sets/%d",
npc = "http://www.wowdb.com/npcs/%d",
spell = "http://www.wowdb.com/spells/%d",
});
mog:AddURL("EVOWoW",{
fav = "Interface\\AddOns\\MogIt\\Images\\fav_wow",
item = "https://wotlk.evowow.com/?item=%d",
set = "https://wotlk.evowow.com/?itemset=%d",
npc = "http://www.wowdb.com/?npcs/%d",
spell = "http://www.wowdb.com/?spells/%d",
compare = function(tbl)
local str;
for k,v in pairs(tbl) do
if str then
str = str..v..";";
else
str = "https://wotlk.evowow.com/?compare="..v..";";
end
end
return str;
end,
});
mog:AddURL("Rising-Gods",{
fav = "Interface\\AddOns\\MogIt\\Images\\fav_wow",
item = "https://db.rising-gods.de/?item=%d",
set = "https://db.rising-gods.de/?item-sets/%d",
npc = "https://db.rising-gods.de/?npcs/%d",
spell = "https://db.rising-gods.de/?spells/%d",
compare = function(tbl)
local str;
for k,v in pairs(tbl) do
if str then
str = str..v..";";
else
str = "https://db.rising-gods.de/?compare="..v..";";
end
end
return str;
end,
});
mog:AddURL("WOWDB",{
fav = "Interface\\AddOns\\MogIt\\Images\\fav_mmo",
item = "http://www.wowdb.com/items/%d",
set = "http://www.wowdb.com/item-sets/%d",
npc = "http://www.wowdb.com/npcs/%d",
spell = "http://www.wowdb.com/spells/%d",
});
mog:AddURL("Wowpedia",{
fav = "Interface\\AddOns\\MogIt\\Images\\fav_wp",
item = "http://www.wowpedia.org/index.php?search=\"{{elinks-item|%d}}\"",
set = "http://www.wowpedia.org/index.php?search=\"{{elinks-set|%d}}\"",
npc = "http://www.wowpedia.org/index.php?search=\"{{elinks-NPC|%d}}\"",
spell = "http://www.wowpedia.org/index.php?search=\"{{elinks-spell|%d}}\"",
});
mog:AddURL("Buffed.de",{
fav = "Interface\\AddOns\\MogIt\\Images\\fav_buff",
item = "http://wowdata.buffed.de/?i=%d",
set = "http://wowdata.buffed.de/?set=%d",
npc = "http://wowdata.buffed.de/?n=%d",
spell = "http://wowdata.buffed.de/?s=%d",
compare = function(tbl)
local str;
for k,v in pairs(tbl) do
if str then
str = str..v..";";
else
str = "http://wowdata.buffed.de/itemcompare#"..v..";";
end
end
return str;
end,
});
mog:AddURL("JudgeHype",{
fav = "Interface\\AddOns\\MogIt\\Images\\fav_jh",
item = "http://worldofwarcraft.judgehype.com/?page=objet&w=%d",
npc = "http://worldofwarcraft.judgehype.com/index.php?page=pnj&w=%d",
spell = "http://worldofwarcraft.judgehype.com/index.php?page=spell&w=%d",
});

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
MogIt/Images/MogIt.tga Normal file

Binary file not shown.

BIN
MogIt/Images/dede.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
MogIt/Images/enus.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
MogIt/Images/eses.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
MogIt/Images/esmx.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
MogIt/Images/fav_buff.tga Normal file

Binary file not shown.

BIN
MogIt/Images/fav_jh.tga Normal file

Binary file not shown.

BIN
MogIt/Images/fav_mmo.tga Normal file

Binary file not shown.

BIN
MogIt/Images/fav_tb.tga Normal file

Binary file not shown.

BIN
MogIt/Images/fav_wh.tga Normal file

Binary file not shown.

BIN
MogIt/Images/fav_wow.tga Normal file

Binary file not shown.

BIN
MogIt/Images/fav_wp.tga Normal file

Binary file not shown.

BIN
MogIt/Images/frfr.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
MogIt/Images/itit.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
MogIt/Images/kokr.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
MogIt/Images/ptbr.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
MogIt/Images/ruru.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
MogIt/Images/zhcn.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
MogIt/Images/zhtw.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,57 @@
--- AceConfig-3.0 wrapper library.
-- Provides an API to register an options table with the config registry,
-- as well as associate it with a slash command.
-- @class file
-- @name AceConfig-3.0
-- @release $Id: AceConfig-3.0.lua 969 2010-10-07 02:11:48Z shefki $
--[[
AceConfig-3.0
Very light wrapper library that combines all the AceConfig subcomponents into one more easily used whole.
]]
local MAJOR, MINOR = "AceConfig-3.0", 2
local AceConfig = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConfig then return end
local cfgreg = LibStub("AceConfigRegistry-3.0")
local cfgcmd = LibStub("AceConfigCmd-3.0")
--TODO: local cfgdlg = LibStub("AceConfigDialog-3.0", true)
--TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0", true)
-- Lua APIs
local pcall, error, type, pairs = pcall, error, type, pairs
-- -------------------------------------------------------------------
-- :RegisterOptionsTable(appName, options, slashcmd, persist)
--
-- - appName - (string) application name
-- - options - table or function ref, see AceConfigRegistry
-- - slashcmd - slash command (string) or table with commands, or nil to NOT create a slash command
--- Register a option table with the AceConfig registry.
-- You can supply a slash command (or a table of slash commands) to register with AceConfigCmd directly.
-- @paramsig appName, options [, slashcmd]
-- @param appName The application name for the config table.
-- @param options The option table (or a function to generate one on demand). http://www.wowace.com/addons/ace3/pages/ace-config-3-0-options-tables/
-- @param slashcmd A slash command to register for the option table, or a table of slash commands.
-- @usage
-- local AceConfig = LibStub("AceConfig-3.0")
-- AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"/myslash", "/my"})
function AceConfig:RegisterOptionsTable(appName, options, slashcmd)
local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options)
if not ok then error(msg, 2) end
if slashcmd then
if type(slashcmd) == "table" then
for _,cmd in pairs(slashcmd) do
cfgcmd:CreateChatCommand(cmd, appName)
end
else
cfgcmd:CreateChatCommand(slashcmd, appName)
end
end
end

View 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>

View File

@@ -0,0 +1,787 @@
--- AceConfigCmd-3.0 handles access to an options table through the "command line" interface via the ChatFrames.
-- @class file
-- @name AceConfigCmd-3.0
-- @release $Id: AceConfigCmd-3.0.lua 904 2009-12-13 11:56:37Z nevcairiel $
--[[
AceConfigCmd-3.0
Handles commandline optionstable access
REQUIRES: AceConsole-3.0 for command registration (loaded on demand)
]]
-- TODO: plugin args
local MAJOR, MINOR = "AceConfigCmd-3.0", 12
local AceConfigCmd = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConfigCmd then return end
AceConfigCmd.commands = AceConfigCmd.commands or {}
local commands = AceConfigCmd.commands
local cfgreg = LibStub("AceConfigRegistry-3.0")
local AceConsole -- LoD
local AceConsoleName = "AceConsole-3.0"
-- Lua APIs
local strsub, strsplit, strlower, strmatch, strtrim = string.sub, string.split, string.lower, string.match, string.trim
local format, tonumber, tostring = string.format, tonumber, tostring
local tsort, tinsert = table.sort, table.insert
local select, pairs, next, type = select, pairs, next, type
local error, assert = error, assert
-- WoW APIs
local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub, SELECTED_CHAT_FRAME, DEFAULT_CHAT_FRAME
local L = setmetatable({}, { -- TODO: replace with proper locale
__index = function(self,k) return k end
})
local function print(msg)
(SELECTED_CHAT_FRAME or DEFAULT_CHAT_FRAME):AddMessage(msg)
end
-- constants used by getparam() calls below
local handlertypes = {["table"]=true}
local handlermsg = "expected a table"
local functypes = {["function"]=true, ["string"]=true}
local funcmsg = "expected function or member name"
-- pickfirstset() - picks the first non-nil value and returns it
local function pickfirstset(...)
for i=1,select("#",...) do
if select(i,...)~=nil then
return select(i,...)
end
end
end
-- err() - produce real error() regarding malformed options tables etc
local function err(info,inputpos,msg )
local cmdstr=" "..strsub(info.input, 1, inputpos-1)
error(MAJOR..": /" ..info[0] ..cmdstr ..": "..(msg or "malformed options table"), 2)
end
-- usererr() - produce chatframe message regarding bad slash syntax etc
local function usererr(info,inputpos,msg )
local cmdstr=strsub(info.input, 1, inputpos-1);
print("/" ..info[0] .. " "..cmdstr ..": "..(msg or "malformed options table"))
end
-- callmethod() - call a given named method (e.g. "get", "set") with given arguments
local function callmethod(info, inputpos, tab, methodtype, ...)
local method = info[methodtype]
if not method then
err(info, inputpos, "'"..methodtype.."': not set")
end
info.arg = tab.arg
info.option = tab
info.type = tab.type
if type(method)=="function" then
return method(info, ...)
elseif type(method)=="string" then
if type(info.handler[method])~="function" then
err(info, inputpos, "'"..methodtype.."': '"..method.."' is not a member function of "..tostring(info.handler))
end
return info.handler[method](info.handler, info, ...)
else
assert(false) -- type should have already been checked on read
end
end
-- callfunction() - call a given named function (e.g. "name", "desc") with given arguments
local function callfunction(info, tab, methodtype, ...)
local method = tab[methodtype]
info.arg = tab.arg
info.option = tab
info.type = tab.type
if type(method)=="function" then
return method(info, ...)
else
assert(false) -- type should have already been checked on read
end
end
-- do_final() - do the final step (set/execute) along with validation and confirmation
local function do_final(info, inputpos, tab, methodtype, ...)
if info.validate then
local res = callmethod(info,inputpos,tab,"validate",...)
if type(res)=="string" then
usererr(info, inputpos, "'"..strsub(info.input, inputpos).."' - "..res)
return
end
end
-- console ignores .confirm
callmethod(info,inputpos,tab,methodtype, ...)
end
-- getparam() - used by handle() to retreive and store "handler", "get", "set", etc
local function getparam(info, inputpos, tab, depth, paramname, types, errormsg)
local old,oldat = info[paramname], info[paramname.."_at"]
local val=tab[paramname]
if val~=nil then
if val==false then
val=nil
elseif not types[type(val)] then
err(info, inputpos, "'" .. paramname.. "' - "..errormsg)
end
info[paramname] = val
info[paramname.."_at"] = depth
end
return old,oldat
end
-- iterateargs(tab) - custom iterator that iterates both t.args and t.plugins.*
local dummytable={}
local function iterateargs(tab)
if not tab.plugins then
return pairs(tab.args)
end
local argtabkey,argtab=next(tab.plugins)
local v
return function(_, k)
while argtab do
k,v = next(argtab, k)
if k then return k,v end
if argtab==tab.args then
argtab=nil
else
argtabkey,argtab = next(tab.plugins, argtabkey)
if not argtabkey then
argtab=tab.args
end
end
end
end
end
local function checkhidden(info, inputpos, tab)
if tab.cmdHidden~=nil then
return tab.cmdHidden
end
local hidden = tab.hidden
if type(hidden) == "function" or type(hidden) == "string" then
info.hidden = hidden
hidden = callmethod(info, inputpos, tab, 'hidden')
info.hidden = nil
end
return hidden
end
local function showhelp(info, inputpos, tab, depth, noHead)
if not noHead then
print("|cff33ff99"..info.appName.."|r: Arguments to |cffffff78/"..info[0].."|r "..strsub(info.input,1,inputpos-1)..":")
end
local sortTbl = {} -- [1..n]=name
local refTbl = {} -- [name]=tableref
for k,v in iterateargs(tab) do
if not refTbl[k] then -- a plugin overriding something in .args
tinsert(sortTbl, k)
refTbl[k] = v
end
end
tsort(sortTbl, function(one, two)
local o1 = refTbl[one].order or 100
local o2 = refTbl[two].order or 100
if type(o1) == "function" or type(o1) == "string" then
info.order = o1
info[#info+1] = one
o1 = callmethod(info, inputpos, refTbl[one], "order")
info[#info] = nil
info.order = nil
end
if type(o2) == "function" or type(o1) == "string" then
info.order = o2
info[#info+1] = two
o2 = callmethod(info, inputpos, refTbl[two], "order")
info[#info] = nil
info.order = nil
end
if o1<0 and o2<0 then return o1<o2 end
if o2<0 then return true end
if o1<0 then return false end
if o1==o2 then return tostring(one)<tostring(two) end -- compare names
return o1<o2
end)
for i = 1, #sortTbl do
local k = sortTbl[i]
local v = refTbl[k]
if not checkhidden(info, inputpos, v) then
if v.type ~= "description" and v.type ~= "header" then
-- recursively show all inline groups
local name, desc = v.name, v.desc
if type(name) == "function" then
name = callfunction(info, v, 'name')
end
if type(desc) == "function" then
desc = callfunction(info, v, 'desc')
end
if v.type == "group" and pickfirstset(v.cmdInline, v.inline, false) then
print(" "..(desc or name)..":")
local oldhandler,oldhandler_at = getparam(info, inputpos, v, depth, "handler", handlertypes, handlermsg)
showhelp(info, inputpos, v, depth, true)
info.handler,info.handler_at = oldhandler,oldhandler_at
else
local key = k:gsub(" ", "_")
print(" |cffffff78"..key.."|r - "..(desc or name or ""))
end
end
end
end
end
local function keybindingValidateFunc(text)
if text == nil or text == "NONE" then
return nil
end
text = text:upper()
local shift, ctrl, alt
local modifier
while true do
if text == "-" then
break
end
modifier, text = strsplit('-', text, 2)
if text then
if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then
return false
end
if modifier == "SHIFT" then
if shift then
return false
end
shift = true
end
if modifier == "CTRL" then
if ctrl then
return false
end
ctrl = true
end
if modifier == "ALT" then
if alt then
return false
end
alt = true
end
else
text = modifier
break
end
end
if text == "" then
return false
end
if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and (text:byte() < 128 or text:len() > 4) and not _G["KEY_" .. text] then
return false
end
local s = text
if shift then
s = "SHIFT-" .. s
end
if ctrl then
s = "CTRL-" .. s
end
if alt then
s = "ALT-" .. s
end
return s
end
-- handle() - selfrecursing function that processes input->optiontable
-- - depth - starts at 0
-- - retfalse - return false rather than produce error if a match is not found (used by inlined groups)
local function handle(info, inputpos, tab, depth, retfalse)
if not(type(tab)=="table" and type(tab.type)=="string") then err(info,inputpos) end
-------------------------------------------------------------------
-- Grab hold of handler,set,get,func,etc if set (and remember old ones)
-- Note that we do NOT validate if method names are correct at this stage,
-- the handler may change before they're actually used!
local oldhandler,oldhandler_at = getparam(info,inputpos,tab,depth,"handler",handlertypes,handlermsg)
local oldset,oldset_at = getparam(info,inputpos,tab,depth,"set",functypes,funcmsg)
local oldget,oldget_at = getparam(info,inputpos,tab,depth,"get",functypes,funcmsg)
local oldfunc,oldfunc_at = getparam(info,inputpos,tab,depth,"func",functypes,funcmsg)
local oldvalidate,oldvalidate_at = getparam(info,inputpos,tab,depth,"validate",functypes,funcmsg)
--local oldconfirm,oldconfirm_at = getparam(info,inputpos,tab,depth,"confirm",functypes,funcmsg)
-------------------------------------------------------------------
-- Act according to .type of this table
if tab.type=="group" then
------------ group --------------------------------------------
if type(tab.args)~="table" then err(info, inputpos) end
if tab.plugins and type(tab.plugins)~="table" then err(info,inputpos) end
-- grab next arg from input
local _,nextpos,arg = (info.input):find(" *([^ ]+) *", inputpos)
if not arg then
showhelp(info, inputpos, tab, depth)
return
end
nextpos=nextpos+1
-- loop .args and try to find a key with a matching name
for k,v in iterateargs(tab) do
if not(type(k)=="string" and type(v)=="table" and type(v.type)=="string") then err(info,inputpos, "options table child '"..tostring(k).."' is malformed") end
-- is this child an inline group? if so, traverse into it
if v.type=="group" and pickfirstset(v.cmdInline, v.inline, false) then
info[depth+1] = k
if handle(info, inputpos, v, depth+1, true)==false then
info[depth+1] = nil
-- wasn't found in there, but that's ok, we just keep looking down here
else
return -- done, name was found in inline group
end
-- matching name and not a inline group
elseif strlower(arg)==strlower(k:gsub(" ", "_")) then
info[depth+1] = k
return handle(info,nextpos,v,depth+1)
end
end
-- no match
if retfalse then
-- restore old infotable members and return false to indicate failure
info.handler,info.handler_at = oldhandler,oldhandler_at
info.set,info.set_at = oldset,oldset_at
info.get,info.get_at = oldget,oldget_at
info.func,info.func_at = oldfunc,oldfunc_at
info.validate,info.validate_at = oldvalidate,oldvalidate_at
--info.confirm,info.confirm_at = oldconfirm,oldconfirm_at
return false
end
-- couldn't find the command, display error
usererr(info, inputpos, "'"..arg.."' - " .. L["unknown argument"])
return
end
local str = strsub(info.input,inputpos);
if tab.type=="execute" then
------------ execute --------------------------------------------
do_final(info, inputpos, tab, "func")
elseif tab.type=="input" then
------------ input --------------------------------------------
local res = true
if tab.pattern then
if not(type(tab.pattern)=="string") then err(info, inputpos, "'pattern' - expected a string") end
if not strmatch(str, tab.pattern) then
usererr(info, inputpos, "'"..str.."' - " .. L["invalid input"])
return
end
end
do_final(info, inputpos, tab, "set", str)
elseif tab.type=="toggle" then
------------ toggle --------------------------------------------
local b
local str = strtrim(strlower(str))
if str=="" then
b = callmethod(info, inputpos, tab, "get")
if tab.tristate then
--cycle in true, nil, false order
if b then
b = nil
elseif b == nil then
b = false
else
b = true
end
else
b = not b
end
elseif str==L["on"] then
b = true
elseif str==L["off"] then
b = false
elseif tab.tristate and str==L["default"] then
b = nil
else
if tab.tristate then
usererr(info, inputpos, format(L["'%s' - expected 'on', 'off' or 'default', or no argument to toggle."], str))
else
usererr(info, inputpos, format(L["'%s' - expected 'on' or 'off', or no argument to toggle."], str))
end
return
end
do_final(info, inputpos, tab, "set", b)
elseif tab.type=="range" then
------------ range --------------------------------------------
local val = tonumber(str)
if not val then
usererr(info, inputpos, "'"..str.."' - "..L["expected number"])
return
end
if type(info.step)=="number" then
val = val- (val % info.step)
end
if type(info.min)=="number" and val<info.min then
usererr(info, inputpos, val.." - "..format(L["must be equal to or higher than %s"], tostring(info.min)) )
return
end
if type(info.max)=="number" and val>info.max then
usererr(info, inputpos, val.." - "..format(L["must be equal to or lower than %s"], tostring(info.max)) )
return
end
do_final(info, inputpos, tab, "set", val)
elseif tab.type=="select" then
------------ select ------------------------------------
local str = strtrim(strlower(str))
local values = tab.values
if type(values) == "function" or type(values) == "string" then
info.values = values
values = callmethod(info, inputpos, tab, "values")
info.values = nil
end
if str == "" then
local b = callmethod(info, inputpos, tab, "get")
local fmt = "|cffffff78- [%s]|r %s"
local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
print(L["Options for |cffffff78"..info[#info].."|r:"])
for k, v in pairs(values) do
if b == k then
print(fmt_sel:format(k, v))
else
print(fmt:format(k, v))
end
end
return
end
local ok
for k,v in pairs(values) do
if strlower(k)==str then
str = k -- overwrite with key (in case of case mismatches)
ok = true
break
end
end
if not ok then
usererr(info, inputpos, "'"..str.."' - "..L["unknown selection"])
return
end
do_final(info, inputpos, tab, "set", str)
elseif tab.type=="multiselect" then
------------ multiselect -------------------------------------------
local str = strtrim(strlower(str))
local values = tab.values
if type(values) == "function" or type(values) == "string" then
info.values = values
values = callmethod(info, inputpos, tab, "values")
info.values = nil
end
if str == "" then
local fmt = "|cffffff78- [%s]|r %s"
local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
print(L["Options for |cffffff78"..info[#info].."|r (multiple possible):"])
for k, v in pairs(values) do
if callmethod(info, inputpos, tab, "get", k) then
print(fmt_sel:format(k, v))
else
print(fmt:format(k, v))
end
end
return
end
--build a table of the selections, checking that they exist
--parse for =on =off =default in the process
--table will be key = true for options that should toggle, key = [on|off|default] for options to be set
local sels = {}
for v in str:gmatch("[^ ]+") do
--parse option=on etc
local opt, val = v:match('(.+)=(.+)')
--get option if toggling
if not opt then
opt = v
end
--check that the opt is valid
local ok
for k,v in pairs(values) do
if strlower(k)==opt then
opt = k -- overwrite with key (in case of case mismatches)
ok = true
break
end
end
if not ok then
usererr(info, inputpos, "'"..opt.."' - "..L["unknown selection"])
return
end
--check that if val was supplied it is valid
if val then
if val == L["on"] or val == L["off"] or (tab.tristate and val == L["default"]) then
--val is valid insert it
sels[opt] = val
else
if tab.tristate then
usererr(info, inputpos, format(L["'%s' '%s' - expected 'on', 'off' or 'default', or no argument to toggle."], v, val))
else
usererr(info, inputpos, format(L["'%s' '%s' - expected 'on' or 'off', or no argument to toggle."], v, val))
end
return
end
else
-- no val supplied, toggle
sels[opt] = true
end
end
for opt, val in pairs(sels) do
local newval
if (val == true) then
--toggle the option
local b = callmethod(info, inputpos, tab, "get", opt)
if tab.tristate then
--cycle in true, nil, false order
if b then
b = nil
elseif b == nil then
b = false
else
b = true
end
else
b = not b
end
newval = b
else
--set the option as specified
if val==L["on"] then
newval = true
elseif val==L["off"] then
newval = false
elseif val==L["default"] then
newval = nil
end
end
do_final(info, inputpos, tab, "set", opt, newval)
end
elseif tab.type=="color" then
------------ color --------------------------------------------
local str = strtrim(strlower(str))
if str == "" then
--TODO: Show current value
return
end
local r, g, b, a
if tab.hasAlpha then
if str:len() == 8 and str:find("^%x*$") then
--parse a hex string
r,g,b,a = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255, tonumber(str:sub(7, 8), 16) / 255
else
--parse seperate values
r,g,b,a = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+) ([%d%.]+)$")
r,g,b,a = tonumber(r), tonumber(g), tonumber(b), tonumber(a)
end
if not (r and g and b and a) then
usererr(info, inputpos, format(L["'%s' - expected 'RRGGBBAA' or 'r g b a'."], str))
return
end
if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 and a >= 0.0 and a <= 1.0 then
--values are valid
elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 and a >= 0 and a <= 255 then
--values are valid 0..255, convert to 0..1
r = r / 255
g = g / 255
b = b / 255
a = a / 255
else
--values are invalid
usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0..1 or 0..255."], str))
end
else
a = 1.0
if str:len() == 6 and str:find("^%x*$") then
--parse a hex string
r,g,b = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255
else
--parse seperate values
r,g,b = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+)$")
r,g,b = tonumber(r), tonumber(g), tonumber(b)
end
if not (r and g and b) then
usererr(info, inputpos, format(L["'%s' - expected 'RRGGBB' or 'r g b'."], str))
return
end
if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 then
--values are valid
elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 then
--values are valid 0..255, convert to 0..1
r = r / 255
g = g / 255
b = b / 255
else
--values are invalid
usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0-1 or 0-255."], str))
end
end
do_final(info, inputpos, tab, "set", r,g,b,a)
elseif tab.type=="keybinding" then
------------ keybinding --------------------------------------------
local str = strtrim(strlower(str))
if str == "" then
--TODO: Show current value
return
end
local value = keybindingValidateFunc(str:upper())
if value == false then
usererr(info, inputpos, format(L["'%s' - Invalid Keybinding."], str))
return
end
do_final(info, inputpos, tab, "set", value)
elseif tab.type=="description" then
------------ description --------------------
-- ignore description, GUI config only
else
err(info, inputpos, "unknown options table item type '"..tostring(tab.type).."'")
end
end
--- Handle the chat command.
-- This is usually called from a chat command handler to parse the command input as operations on an aceoptions table.\\
-- AceConfigCmd uses this function internally when a slash command is registered with `:CreateChatCommand`
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param input The commandline input (as given by the WoW handler, i.e. without the command itself)
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceConsole-3.0")
-- -- Use AceConsole-3.0 to register a Chat Command
-- MyAddon:RegisterChatCommand("mychat", "ChatCommand")
--
-- -- Show the GUI if no input is supplied, otherwise handle the chat input.
-- function MyAddon:ChatCommand(input)
-- -- Assuming "MyOptions" is the appName of a valid options table
-- if not input or input:trim() == "" then
-- LibStub("AceConfigDialog-3.0"):Open("MyOptions")
-- else
-- LibStub("AceConfigCmd-3.0").HandleCommand(MyAddon, "mychat", "MyOptions", input)
-- end
-- end
function AceConfigCmd:HandleCommand(slashcmd, appName, input)
local optgetter = cfgreg:GetOptionsTable(appName)
if not optgetter then
error([[Usage: HandleCommand("slashcmd", "appName", "input"): 'appName' - no options table "]]..tostring(appName)..[[" has been registered]], 2)
end
local options = assert( optgetter("cmd", MAJOR) )
local info = { -- Don't try to recycle this, it gets handed off to callbacks and whatnot
[0] = slashcmd,
appName = appName,
options = options,
input = input,
self = self,
handler = self,
uiType = "cmd",
uiName = MAJOR,
}
handle(info, 1, options, 0) -- (info, inputpos, table, depth)
end
--- Utility function to create a slash command handler.
-- Also registers tab completion with AceTab
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
-- @param appName The application name as given to `:RegisterOptionsTable()`
function AceConfigCmd:CreateChatCommand(slashcmd, appName)
if not AceConsole then
AceConsole = LibStub(AceConsoleName)
end
if AceConsole.RegisterChatCommand(self, slashcmd, function(input)
AceConfigCmd.HandleCommand(self, slashcmd, appName, input) -- upgradable
end,
true) then -- succesfully registered so lets get the command -> app table in
commands[slashcmd] = appName
end
end
--- Utility function that returns the options table that belongs to a slashcommand.
-- Designed to be used for the AceTab interface.
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
-- @return The options table associated with the slash command (or nil if the slash command was not registered)
function AceConfigCmd:GetChatCommandOptions(slashcmd)
return commands[slashcmd]
end

View 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>

File diff suppressed because it is too large Load Diff

View 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>

View File

@@ -0,0 +1,346 @@
--- AceConfigRegistry-3.0 handles central registration of options tables in use by addons and modules.\\
-- Options tables can be registered as raw tables, OR as function refs that return a table.\\
-- Such functions receive three arguments: "uiType", "uiName", "appName". \\
-- * Valid **uiTypes**: "cmd", "dropdown", "dialog". This is verified by the library at call time. \\
-- * The **uiName** field is expected to contain the full name of the calling addon, including version, e.g. "FooBar-1.0". This is verified by the library at call time.\\
-- * The **appName** field is the options table name as given at registration time \\
--
-- :IterateOptionsTables() (and :GetOptionsTable() if only given one argument) return a function reference that the requesting config handling addon must call with valid "uiType", "uiName".
-- @class file
-- @name AceConfigRegistry-3.0
-- @release $Id: AceConfigRegistry-3.0.lua 921 2010-05-09 15:49:14Z nevcairiel $
local MAJOR, MINOR = "AceConfigRegistry-3.0", 12
local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConfigRegistry then return end
AceConfigRegistry.tables = AceConfigRegistry.tables or {}
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
if not AceConfigRegistry.callbacks then
AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry)
end
-- Lua APIs
local tinsert, tconcat = table.insert, table.concat
local strfind, strmatch = string.find, string.match
local type, tostring, select, pairs = type, tostring, select, pairs
local error, assert = error, assert
-----------------------------------------------------------------------
-- Validating options table consistency:
AceConfigRegistry.validated = {
-- list of options table names ran through :ValidateOptionsTable automatically.
-- CLEARED ON PURPOSE, since newer versions may have newer validators
cmd = {},
dropdown = {},
dialog = {},
}
local function err(msg, errlvl, ...)
local t = {}
for i=select("#",...),1,-1 do
tinsert(t, (select(i, ...)))
end
error(MAJOR..":ValidateOptionsTable(): "..tconcat(t,".")..msg, errlvl+2)
end
local isstring={["string"]=true, _="string"}
local isstringfunc={["string"]=true,["function"]=true, _="string or funcref"}
local istable={["table"]=true, _="table"}
local ismethodtable={["table"]=true,["string"]=true,["function"]=true, _="methodname, funcref or table"}
local optstring={["nil"]=true,["string"]=true, _="string"}
local optstringfunc={["nil"]=true,["string"]=true,["function"]=true, _="string or funcref"}
local optnumber={["nil"]=true,["number"]=true, _="number"}
local optmethod={["nil"]=true,["string"]=true,["function"]=true, _="methodname or funcref"}
local optmethodfalse={["nil"]=true,["string"]=true,["function"]=true,["boolean"]={[false]=true}, _="methodname, funcref or false"}
local optmethodnumber={["nil"]=true,["string"]=true,["function"]=true,["number"]=true, _="methodname, funcref or number"}
local optmethodtable={["nil"]=true,["string"]=true,["function"]=true,["table"]=true, _="methodname, funcref or table"}
local optmethodbool={["nil"]=true,["string"]=true,["function"]=true,["boolean"]=true, _="methodname, funcref or boolean"}
local opttable={["nil"]=true,["table"]=true, _="table"}
local optbool={["nil"]=true,["boolean"]=true, _="boolean"}
local optboolnumber={["nil"]=true,["boolean"]=true,["number"]=true, _="boolean or number"}
local basekeys={
type=isstring,
name=isstringfunc,
desc=optstringfunc,
descStyle=optstring,
order=optmethodnumber,
validate=optmethodfalse,
confirm=optmethodbool,
confirmText=optstring,
disabled=optmethodbool,
hidden=optmethodbool,
guiHidden=optmethodbool,
dialogHidden=optmethodbool,
dropdownHidden=optmethodbool,
cmdHidden=optmethodbool,
icon=optstringfunc,
iconCoords=optmethodtable,
handler=opttable,
get=optmethodfalse,
set=optmethodfalse,
func=optmethodfalse,
arg={["*"]=true},
width=optstring,
}
local typedkeys={
header={},
description={
image=optstringfunc,
imageCoords=optmethodtable,
imageHeight=optnumber,
imageWidth=optnumber,
fontSize=optstringfunc,
},
group={
args=istable,
plugins=opttable,
inline=optbool,
cmdInline=optbool,
guiInline=optbool,
dropdownInline=optbool,
dialogInline=optbool,
childGroups=optstring,
},
execute={
image=optstringfunc,
imageCoords=optmethodtable,
imageHeight=optnumber,
imageWidth=optnumber,
},
input={
pattern=optstring,
usage=optstring,
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
multiline=optboolnumber,
},
toggle={
tristate=optbool,
image=optstringfunc,
imageCoords=optmethodtable,
},
tristate={
},
range={
min=optnumber,
softMin=optnumber,
max=optnumber,
softMax=optnumber,
step=optnumber,
bigStep=optnumber,
isPercent=optbool,
},
select={
values=ismethodtable,
style={
["nil"]=true,
["string"]={dropdown=true,radio=true},
_="string: 'dropdown' or 'radio'"
},
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
},
multiselect={
values=ismethodtable,
style=optstring,
tristate=optbool,
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
},
color={
hasAlpha=optbool,
},
keybinding={
-- TODO
},
}
local function validateKey(k,errlvl,...)
errlvl=(errlvl or 0)+1
if type(k)~="string" then
err("["..tostring(k).."] - key is not a string", errlvl,...)
end
if strfind(k, "[%c\127]") then
err("["..tostring(k).."] - key name contained control characters", errlvl,...)
end
end
local function validateVal(v, oktypes, errlvl,...)
errlvl=(errlvl or 0)+1
local isok=oktypes[type(v)] or oktypes["*"]
if not isok then
err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl,...)
end
if type(isok)=="table" then -- isok was a table containing specific values to be tested for!
if not isok[v] then
err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl,...)
end
end
end
local function validate(options,errlvl,...)
errlvl=(errlvl or 0)+1
-- basic consistency
if type(options)~="table" then
err(": expected a table, got a "..type(options), errlvl,...)
end
if type(options.type)~="string" then
err(".type: expected a string, got a "..type(options.type), errlvl,...)
end
-- get type and 'typedkeys' member
local tk = typedkeys[options.type]
if not tk then
err(".type: unknown type '"..options.type.."'", errlvl,...)
end
-- make sure that all options[] are known parameters
for k,v in pairs(options) do
if not (tk[k] or basekeys[k]) then
err(": unknown parameter", errlvl,tostring(k),...)
end
end
-- verify that required params are there, and that everything is the right type
for k,oktypes in pairs(basekeys) do
validateVal(options[k], oktypes, errlvl,k,...)
end
for k,oktypes in pairs(tk) do
validateVal(options[k], oktypes, errlvl,k,...)
end
-- extra logic for groups
if options.type=="group" then
for k,v in pairs(options.args) do
validateKey(k,errlvl,"args",...)
validate(v, errlvl,k,"args",...)
end
if options.plugins then
for plugname,plugin in pairs(options.plugins) do
if type(plugin)~="table" then
err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname),"plugins",...)
end
for k,v in pairs(plugin) do
validateKey(k,errlvl,tostring(plugname),"plugins",...)
validate(v, errlvl,k,tostring(plugname),"plugins",...)
end
end
end
end
end
--- Validates basic structure and integrity of an options table \\
-- Does NOT verify that get/set etc actually exist, since they can be defined at any depth
-- @param options The table to be validated
-- @param name The name of the table to be validated (shown in any error message)
-- @param errlvl (optional number) error level offset, default 0 (=errors point to the function calling :ValidateOptionsTable)
function AceConfigRegistry:ValidateOptionsTable(options,name,errlvl)
errlvl=(errlvl or 0)+1
name = name or "Optionstable"
if not options.name then
options.name=name -- bit of a hack, the root level doesn't really need a .name :-/
end
validate(options,errlvl,name)
end
--- Fires a "ConfigTableChange" callback for those listening in on it, allowing config GUIs to refresh.
-- You should call this function if your options table changed from any outside event, like a game event
-- or a timer.
-- @param appName The application name as given to `:RegisterOptionsTable()`
function AceConfigRegistry:NotifyChange(appName)
if not AceConfigRegistry.tables[appName] then return end
AceConfigRegistry.callbacks:Fire("ConfigTableChange", appName)
end
-- -------------------------------------------------------------------
-- Registering and retreiving options tables:
-- validateGetterArgs: helper function for :GetOptionsTable (or, rather, the getter functions returned by it)
local function validateGetterArgs(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+2
if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then
error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl)
end
if not strmatch(uiName, "[A-Za-z]%-[0-9]") then -- Expecting e.g. "MyLib-1.2"
error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", errlvl)
end
end
--- Register an options table with the config registry.
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param options The options table, OR a function reference that generates it on demand. \\
-- See the top of the page for info on arguments passed to such functions.
function AceConfigRegistry:RegisterOptionsTable(appName, options)
if type(options)=="table" then
if options.type~="group" then -- quick sanity checker
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - missing type='group' member in root group", 2)
end
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+1
validateGetterArgs(uiType, uiName, errlvl)
if not AceConfigRegistry.validated[uiType][appName] then
AceConfigRegistry:ValidateOptionsTable(options, appName, errlvl) -- upgradable
AceConfigRegistry.validated[uiType][appName] = true
end
return options
end
elseif type(options)=="function" then
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+1
validateGetterArgs(uiType, uiName, errlvl)
local tab = assert(options(uiType, uiName, appName))
if not AceConfigRegistry.validated[uiType][appName] then
AceConfigRegistry:ValidateOptionsTable(tab, appName, errlvl) -- upgradable
AceConfigRegistry.validated[uiType][appName] = true
end
return tab
end
else
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - expected table or function reference", 2)
end
end
--- Returns an iterator of ["appName"]=funcref pairs
function AceConfigRegistry:IterateOptionsTables()
return pairs(AceConfigRegistry.tables)
end
--- Query the registry for a specific options table.
-- If only appName is given, a function is returned which you
-- can call with (uiType,uiName) to get the table.\\
-- If uiType&uiName are given, the table is returned.
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param uiType The type of UI to get the table for, one of "cmd", "dropdown", "dialog"
-- @param uiName The name of the library/addon querying for the table, e.g. "MyLib-1.0"
function AceConfigRegistry:GetOptionsTable(appName, uiType, uiName)
local f = AceConfigRegistry.tables[appName]
if not f then
return nil
end
if uiType then
return f(uiType,uiName,1) -- get the table for us
else
return f -- return the function
end
end

View 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>

View File

@@ -0,0 +1,728 @@
--- **AceDB-3.0** manages the SavedVariables of your addon.
-- It offers profile management, smart defaults and namespaces for modules.\\
-- Data can be saved in different data-types, depending on its intended usage.
-- The most common data-type is the `profile` type, which allows the user to choose
-- the active profile, and manage the profiles of all of his characters.\\
-- The following data types are available:
-- * **char** Character-specific data. Every character has its own database.
-- * **realm** Realm-specific data. All of the players characters on the same realm share this database.
-- * **class** Class-specific data. All of the players characters of the same class share this database.
-- * **race** Race-specific data. All of the players characters of the same race share this database.
-- * **faction** Faction-specific data. All of the players characters of the same faction share this database.
-- * **factionrealm** Faction and realm specific data. All of the players characters on the same realm and of the same faction share this database.
-- * **global** Global Data. All characters on the same account share this database.
-- * **profile** Profile-specific data. All characters using the same profile share this database. The user can control which profile should be used.
--
-- Creating a new Database using the `:New` function will return a new DBObject. A database will inherit all functions
-- of the DBObjectLib listed here. \\
-- If you create a new namespaced child-database (`:RegisterNamespace`), you'll get a DBObject as well, but note
-- that the child-databases cannot individually change their profile, and are linked to their parents profile - and because of that,
-- the profile related APIs are not available. Only `:RegisterDefaults` and `:ResetProfile` are available on child-databases.
--
-- For more details on how to use AceDB-3.0, see the [[AceDB-3.0 Tutorial]].
--
-- You may also be interested in [[libdualspec-1-0|LibDualSpec-1.0]] to do profile switching automatically when switching specs.
--
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("DBExample")
--
-- -- declare defaults to be used in the DB
-- local defaults = {
-- profile = {
-- setting = true,
-- }
-- }
--
-- function MyAddon:OnInitialize()
-- -- Assuming the .toc says ## SavedVariables: MyAddonDB
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
-- end
-- @class file
-- @name AceDB-3.0.lua
-- @release $Id: AceDB-3.0.lua 940 2010-06-19 08:01:47Z nevcairiel $
local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 21
local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
if not AceDB then return end -- No upgrade needed
-- Lua APIs
local type, pairs, next, error = type, pairs, next, error
local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
-- WoW APIs
local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub
AceDB.db_registry = AceDB.db_registry or {}
AceDB.frame = AceDB.frame or CreateFrame("Frame")
local CallbackHandler
local CallbackDummy = { Fire = function() end }
local DBObjectLib = {}
--[[-------------------------------------------------------------------------
AceDB Utility Functions
---------------------------------------------------------------------------]]
-- Simple shallow copy for copying defaults
local function copyTable(src, dest)
if type(dest) ~= "table" then dest = {} end
if type(src) == "table" then
for k,v in pairs(src) do
if type(v) == "table" then
-- try to index the key first so that the metatable creates the defaults, if set, and use that table
v = copyTable(v, dest[k])
end
dest[k] = v
end
end
return dest
end
-- Called to add defaults to a section of the database
--
-- When a ["*"] default section is indexed with a new key, a table is returned
-- and set in the host table. These tables must be cleaned up by removeDefaults
-- in order to ensure we don't write empty default tables.
local function copyDefaults(dest, src)
-- this happens if some value in the SV overwrites our default value with a non-table
--if type(dest) ~= "table" then return end
for k, v in pairs(src) do
if k == "*" or k == "**" then
if type(v) == "table" then
-- This is a metatable used for table defaults
local mt = {
-- This handles the lookup and creation of new subtables
__index = function(t,k)
if k == nil then return nil end
local tbl = {}
copyDefaults(tbl, v)
rawset(t, k, tbl)
return tbl
end,
}
setmetatable(dest, mt)
-- handle already existing tables in the SV
for dk, dv in pairs(dest) do
if not rawget(src, dk) and type(dv) == "table" then
copyDefaults(dv, v)
end
end
else
-- Values are not tables, so this is just a simple return
local mt = {__index = function(t,k) return k~=nil and v or nil end}
setmetatable(dest, mt)
end
elseif type(v) == "table" then
if not rawget(dest, k) then rawset(dest, k, {}) end
if type(dest[k]) == "table" then
copyDefaults(dest[k], v)
if src['**'] then
copyDefaults(dest[k], src['**'])
end
end
else
if rawget(dest, k) == nil then
rawset(dest, k, v)
end
end
end
end
-- Called to remove all defaults in the default table from the database
local function removeDefaults(db, defaults, blocker)
-- remove all metatables from the db, so we don't accidentally create new sub-tables through them
setmetatable(db, nil)
-- loop through the defaults and remove their content
for k,v in pairs(defaults) do
if k == "*" or k == "**" then
if type(v) == "table" then
-- Loop through all the actual k,v pairs and remove
for key, value in pairs(db) do
if type(value) == "table" then
-- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables
if defaults[key] == nil and (not blocker or blocker[key] == nil) then
removeDefaults(value, v)
-- if the table is empty afterwards, remove it
if next(value) == nil then
db[key] = nil
end
-- if it was specified, only strip ** content, but block values which were set in the key table
elseif k == "**" then
removeDefaults(value, v, defaults[key])
end
end
end
elseif k == "*" then
-- check for non-table default
for key, value in pairs(db) do
if defaults[key] == nil and v == value then
db[key] = nil
end
end
end
elseif type(v) == "table" and type(db[k]) == "table" then
-- if a blocker was set, dive into it, to allow multi-level defaults
removeDefaults(db[k], v, blocker and blocker[k])
if next(db[k]) == nil then
db[k] = nil
end
else
-- check if the current value matches the default, and that its not blocked by another defaults table
if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then
db[k] = nil
end
end
end
end
-- This is called when a table section is first accessed, to set up the defaults
local function initSection(db, section, svstore, key, defaults)
local sv = rawget(db, "sv")
local tableCreated
if not sv[svstore] then sv[svstore] = {} end
if not sv[svstore][key] then
sv[svstore][key] = {}
tableCreated = true
end
local tbl = sv[svstore][key]
if defaults then
copyDefaults(tbl, defaults)
end
rawset(db, section, tbl)
return tableCreated, tbl
end
-- Metatable to handle the dynamic creation of sections and copying of sections.
local dbmt = {
__index = function(t, section)
local keys = rawget(t, "keys")
local key = keys[section]
if key then
local defaultTbl = rawget(t, "defaults")
local defaults = defaultTbl and defaultTbl[section]
if section == "profile" then
local new = initSection(t, section, "profiles", key, defaults)
if new then
-- Callback: OnNewProfile, database, newProfileKey
t.callbacks:Fire("OnNewProfile", t, key)
end
elseif section == "profiles" then
local sv = rawget(t, "sv")
if not sv.profiles then sv.profiles = {} end
rawset(t, "profiles", sv.profiles)
elseif section == "global" then
local sv = rawget(t, "sv")
if not sv.global then sv.global = {} end
if defaults then
copyDefaults(sv.global, defaults)
end
rawset(t, section, sv.global)
else
initSection(t, section, section, key, defaults)
end
end
return rawget(t, section)
end
}
local function validateDefaults(defaults, keyTbl, offset)
if not defaults then return end
offset = offset or 0
for k in pairs(defaults) do
if not keyTbl[k] or k == "profiles" then
error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset)
end
end
end
local preserve_keys = {
["callbacks"] = true,
["RegisterCallback"] = true,
["UnregisterCallback"] = true,
["UnregisterAllCallbacks"] = true,
["children"] = true,
}
local realmKey = GetRealmName()
local charKey = UnitName("player") .. " - " .. realmKey
local _, classKey = UnitClass("player")
local _, raceKey = UnitRace("player")
local factionKey = UnitFactionGroup("player")
local factionrealmKey = factionKey .. " - " .. realmKey
-- Actual database initialization function
local function initdb(sv, defaults, defaultProfile, olddb, parent)
-- Generate the database keys for each section
-- map "true" to our "Default" profile
if defaultProfile == true then defaultProfile = "Default" end
local profileKey
if not parent then
-- Make a container for profile keys
if not sv.profileKeys then sv.profileKeys = {} end
-- Try to get the profile selected from the char db
profileKey = sv.profileKeys[charKey] or defaultProfile or charKey
-- save the selected profile for later
sv.profileKeys[charKey] = profileKey
else
-- Use the profile of the parents DB
profileKey = parent.keys.profile or defaultProfile or charKey
-- clear the profileKeys in the DB, namespaces don't need to store them
sv.profileKeys = nil
end
-- This table contains keys that enable the dynamic creation
-- of each section of the table. The 'global' and 'profiles'
-- have a key of true, since they are handled in a special case
local keyTbl= {
["char"] = charKey,
["realm"] = realmKey,
["class"] = classKey,
["race"] = raceKey,
["faction"] = factionKey,
["factionrealm"] = factionrealmKey,
["profile"] = profileKey,
["global"] = true,
["profiles"] = true,
}
validateDefaults(defaults, keyTbl, 1)
-- This allows us to use this function to reset an entire database
-- Clear out the old database
if olddb then
for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end
end
-- Give this database the metatable so it initializes dynamically
local db = setmetatable(olddb or {}, dbmt)
if not rawget(db, "callbacks") then
-- try to load CallbackHandler-1.0 if it loaded after our library
if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end
db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy
end
-- Copy methods locally into the database object, to avoid hitting
-- the metatable when calling methods
if not parent then
for name, func in pairs(DBObjectLib) do
db[name] = func
end
else
-- hack this one in
db.RegisterDefaults = DBObjectLib.RegisterDefaults
db.ResetProfile = DBObjectLib.ResetProfile
end
-- Set some properties in the database object
db.profiles = sv.profiles
db.keys = keyTbl
db.sv = sv
--db.sv_name = name
db.defaults = defaults
db.parent = parent
-- store the DB in the registry
AceDB.db_registry[db] = true
return db
end
-- handle PLAYER_LOGOUT
-- strip all defaults from all databases
-- and cleans up empty sections
local function logoutHandler(frame, event)
if event == "PLAYER_LOGOUT" then
for db in pairs(AceDB.db_registry) do
db.callbacks:Fire("OnDatabaseShutdown", db)
db:RegisterDefaults(nil)
-- cleanup sections that are empty without defaults
local sv = rawget(db, "sv")
for section in pairs(db.keys) do
if rawget(sv, section) then
-- global is special, all other sections have sub-entrys
-- also don't delete empty profiles on main dbs, only on namespaces
if section ~= "global" and (section ~= "profiles" or rawget(db, "parent")) then
for key in pairs(sv[section]) do
if not next(sv[section][key]) then
sv[section][key] = nil
end
end
end
if not next(sv[section]) then
sv[section] = nil
end
end
end
end
end
end
AceDB.frame:RegisterEvent("PLAYER_LOGOUT")
AceDB.frame:SetScript("OnEvent", logoutHandler)
--[[-------------------------------------------------------------------------
AceDB Object Method Definitions
---------------------------------------------------------------------------]]
--- Sets the defaults table for the given database object by clearing any
-- that are currently set, and then setting the new defaults.
-- @param defaults A table of defaults for this database
function DBObjectLib:RegisterDefaults(defaults)
if defaults and type(defaults) ~= "table" then
error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2)
end
validateDefaults(defaults, self.keys)
-- Remove any currently set defaults
if self.defaults then
for section,key in pairs(self.keys) do
if self.defaults[section] and rawget(self, section) then
removeDefaults(self[section], self.defaults[section])
end
end
end
-- Set the DBObject.defaults table
self.defaults = defaults
-- Copy in any defaults, only touching those sections already created
if defaults then
for section,key in pairs(self.keys) do
if defaults[section] and rawget(self, section) then
copyDefaults(self[section], defaults[section])
end
end
end
end
--- Changes the profile of the database and all of it's namespaces to the
-- supplied named profile
-- @param name The name of the profile to set as the current profile
function DBObjectLib:SetProfile(name)
if type(name) ~= "string" then
error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2)
end
-- changing to the same profile, dont do anything
if name == self.keys.profile then return end
local oldProfile = self.profile
local defaults = self.defaults and self.defaults.profile
-- Callback: OnProfileShutdown, database
self.callbacks:Fire("OnProfileShutdown", self)
if oldProfile and defaults then
-- Remove the defaults from the old profile
removeDefaults(oldProfile, defaults)
end
self.profile = nil
self.keys["profile"] = name
-- if the storage exists, save the new profile
-- this won't exist on namespaces.
if self.sv.profileKeys then
self.sv.profileKeys[charKey] = name
end
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.SetProfile(db, name)
end
end
-- Callback: OnProfileChanged, database, newProfileKey
self.callbacks:Fire("OnProfileChanged", self, name)
end
--- Returns a table with the names of the existing profiles in the database.
-- You can optionally supply a table to re-use for this purpose.
-- @param tbl A table to store the profile names in (optional)
function DBObjectLib:GetProfiles(tbl)
if tbl and type(tbl) ~= "table" then
error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2)
end
-- Clear the container table
if tbl then
for k,v in pairs(tbl) do tbl[k] = nil end
else
tbl = {}
end
local curProfile = self.keys.profile
local i = 0
for profileKey in pairs(self.profiles) do
i = i + 1
tbl[i] = profileKey
if curProfile and profileKey == curProfile then curProfile = nil end
end
-- Add the current profile, if it hasn't been created yet
if curProfile then
i = i + 1
tbl[i] = curProfile
end
return tbl, i
end
--- Returns the current profile name used by the database
function DBObjectLib:GetCurrentProfile()
return self.keys.profile
end
--- Deletes a named profile. This profile must not be the active profile.
-- @param name The name of the profile to be deleted
-- @param silent If true, do not raise an error when the profile does not exist
function DBObjectLib:DeleteProfile(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2)
end
if self.keys.profile == name then
error("Cannot delete the active profile in an AceDBObject.", 2)
end
if not rawget(self.profiles, name) and not silent then
error("Cannot delete profile '" .. name .. "'. It does not exist.", 2)
end
self.profiles[name] = nil
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.DeleteProfile(db, name, true)
end
end
-- Callback: OnProfileDeleted, database, profileKey
self.callbacks:Fire("OnProfileDeleted", self, name)
end
--- Copies a named profile into the current profile, overwriting any conflicting
-- settings.
-- @param name The name of the profile to be copied into the current profile
-- @param silent If true, do not raise an error when the profile does not exist
function DBObjectLib:CopyProfile(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2)
end
if name == self.keys.profile then
error("Cannot have the same source and destination profiles.", 2)
end
if not rawget(self.profiles, name) and not silent then
error("Cannot copy profile '" .. name .. "'. It does not exist.", 2)
end
-- Reset the profile before copying
DBObjectLib.ResetProfile(self, nil, true)
local profile = self.profile
local source = self.profiles[name]
copyTable(source, profile)
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.CopyProfile(db, name, true)
end
end
-- Callback: OnProfileCopied, database, sourceProfileKey
self.callbacks:Fire("OnProfileCopied", self, name)
end
--- Resets the current profile to the default values (if specified).
-- @param noChildren if set to true, the reset will not be populated to the child namespaces of this DB object
-- @param noCallbacks if set to true, won't fire the OnProfileReset callback
function DBObjectLib:ResetProfile(noChildren, noCallbacks)
local profile = self.profile
for k,v in pairs(profile) do
profile[k] = nil
end
local defaults = self.defaults and self.defaults.profile
if defaults then
copyDefaults(profile, defaults)
end
-- populate to child namespaces
if self.children and not noChildren then
for _, db in pairs(self.children) do
DBObjectLib.ResetProfile(db, nil, noCallbacks)
end
end
-- Callback: OnProfileReset, database
if not noCallbacks then
self.callbacks:Fire("OnProfileReset", self)
end
end
--- Resets the entire database, using the string defaultProfile as the new default
-- profile.
-- @param defaultProfile The profile name to use as the default
function DBObjectLib:ResetDB(defaultProfile)
if defaultProfile and type(defaultProfile) ~= "string" then
error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2)
end
local sv = self.sv
for k,v in pairs(sv) do
sv[k] = nil
end
local parent = self.parent
initdb(sv, self.defaults, defaultProfile, self)
-- fix the child namespaces
if self.children then
if not sv.namespaces then sv.namespaces = {} end
for name, db in pairs(self.children) do
if not sv.namespaces[name] then sv.namespaces[name] = {} end
initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self)
end
end
-- Callback: OnDatabaseReset, database
self.callbacks:Fire("OnDatabaseReset", self)
-- Callback: OnProfileChanged, database, profileKey
self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"])
return self
end
--- Creates a new database namespace, directly tied to the database. This
-- is a full scale database in it's own rights other than the fact that
-- it cannot control its profile individually
-- @param name The name of the new namespace
-- @param defaults A table of values to use as defaults
function DBObjectLib:RegisterNamespace(name, defaults)
if type(name) ~= "string" then
error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2)
end
if defaults and type(defaults) ~= "table" then
error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2)
end
if self.children and self.children[name] then
error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2)
end
local sv = self.sv
if not sv.namespaces then sv.namespaces = {} end
if not sv.namespaces[name] then
sv.namespaces[name] = {}
end
local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self)
if not self.children then self.children = {} end
self.children[name] = newDB
return newDB
end
--- Returns an already existing namespace from the database object.
-- @param name The name of the new namespace
-- @param silent if true, the addon is optional, silently return nil if its not found
-- @usage
-- local namespace = self.db:GetNamespace('namespace')
-- @return the namespace object if found
function DBObjectLib:GetNamespace(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:GetNamespace(name): 'name' - string expected.", 2)
end
if not silent and not (self.children and self.children[name]) then
error ("Usage: AceDBObject:GetNamespace(name): 'name' - namespace does not exist.", 2)
end
if not self.children then self.children = {} end
return self.children[name]
end
--[[-------------------------------------------------------------------------
AceDB Exposed Methods
---------------------------------------------------------------------------]]
--- Creates a new database object that can be used to handle database settings and profiles.
-- By default, an empty DB is created, using a character specific profile.
--
-- You can override the default profile used by passing any profile name as the third argument,
-- or by passing //true// as the third argument to use a globally shared profile called "Default".
--
-- Note that there is no token replacement in the default profile name, passing a defaultProfile as "char"
-- will use a profile named "char", and not a character-specific profile.
-- @param tbl The name of variable, or table to use for the database
-- @param defaults A table of database defaults
-- @param defaultProfile The name of the default profile. If not set, a character specific profile will be used as the default.
-- You can also pass //true// to use a shared global profile called "Default".
-- @usage
-- -- Create an empty DB using a character-specific default profile.
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB")
-- @usage
-- -- Create a DB using defaults and using a shared default profile
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
function AceDB:New(tbl, defaults, defaultProfile)
if type(tbl) == "string" then
local name = tbl
tbl = _G[name]
if not tbl then
tbl = {}
_G[name] = tbl
end
end
if type(tbl) ~= "table" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2)
end
if defaults and type(defaults) ~= "table" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2)
end
if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected.", 2)
end
return initdb(tbl, defaults, defaultProfile)
end
-- upgrade existing databases
for db in pairs(AceDB.db_registry) do
if not db.parent then
for name,func in pairs(DBObjectLib) do
db[name] = func
end
else
db.RegisterDefaults = DBObjectLib.RegisterDefaults
db.ResetProfile = DBObjectLib.ResetProfile
end
end

View 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>

View File

@@ -0,0 +1,420 @@
--- AceDBOptions-3.0 provides a universal AceConfig options screen for managing AceDB-3.0 profiles.
-- @class file
-- @name AceDBOptions-3.0
-- @release $Id: AceDBOptions-3.0.lua 938 2010-06-13 07:21:38Z nevcairiel $
local ACEDBO_MAJOR, ACEDBO_MINOR = "AceDBOptions-3.0", 12
local AceDBOptions, oldminor = LibStub:NewLibrary(ACEDBO_MAJOR, ACEDBO_MINOR)
if not AceDBOptions then return end -- No upgrade needed
-- Lua APIs
local pairs, next = pairs, next
-- WoW APIs
local UnitClass = UnitClass
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: NORMAL_FONT_COLOR_CODE, FONT_COLOR_CODE_CLOSE
AceDBOptions.optionTables = AceDBOptions.optionTables or {}
AceDBOptions.handlers = AceDBOptions.handlers or {}
--[[
Localization of AceDBOptions-3.0
]]
local L = {
default = "Default",
intro = "You can change the active database profile, so you can have different settings for every character.",
reset_desc = "Reset the current profile back to its default values, in case your configuration is broken, or you simply want to start over.",
reset = "Reset Profile",
reset_sub = "Reset the current profile to the default",
choose_desc = "You can either create a new profile by entering a name in the editbox, or choose one of the already existing profiles.",
new = "New",
new_sub = "Create a new empty profile.",
choose = "Existing Profiles",
choose_sub = "Select one of your currently available profiles.",
copy_desc = "Copy the settings from one existing profile into the currently active profile.",
copy = "Copy From",
delete_desc = "Delete existing and unused profiles from the database to save space, and cleanup the SavedVariables file.",
delete = "Delete a Profile",
delete_sub = "Deletes a profile from the database.",
delete_confirm = "Are you sure you want to delete the selected profile?",
profiles = "Profiles",
profiles_sub = "Manage Profiles",
current = "Current Profile:",
}
local LOCALE = GetLocale()
if LOCALE == "deDE" then
L["default"] = "Standard"
L["intro"] = "Hier kannst du das aktive Datenbankprofile \195\164ndern, damit du verschiedene Einstellungen f\195\188r jeden Charakter erstellen kannst, wodurch eine sehr flexible Konfiguration m\195\182glich wird."
L["reset_desc"] = "Setzt das momentane Profil auf Standardwerte zur\195\188ck, f\195\188r den Fall das mit der Konfiguration etwas schief lief oder weil du einfach neu starten willst."
L["reset"] = "Profil zur\195\188cksetzen"
L["reset_sub"] = "Das aktuelle Profil auf Standard zur\195\188cksetzen."
L["choose_desc"] = "Du kannst ein neues Profil erstellen, indem du einen neuen Namen in der Eingabebox 'Neu' eingibst, oder w\195\164hle eines der vorhandenen Profile aus."
L["new"] = "Neu"
L["new_sub"] = "Ein neues Profil erstellen."
L["choose"] = "Vorhandene Profile"
L["choose_sub"] = "W\195\164hlt ein bereits vorhandenes Profil aus."
L["copy_desc"] = "Kopiere die Einstellungen von einem vorhandenen Profil in das aktive Profil."
L["copy"] = "Kopieren von..."
L["delete_desc"] = "L\195\182sche vorhandene oder unbenutzte Profile aus der Datenbank um Platz zu sparen und um die SavedVariables Datei 'sauber' zu halten."
L["delete"] = "Profil l\195\182schen"
L["delete_sub"] = "L\195\182scht ein Profil aus der Datenbank."
L["delete_confirm"] = "Willst du das ausgew\195\164hlte Profil wirklich l\195\182schen?"
L["profiles"] = "Profile"
L["profiles_sub"] = "Profile verwalten"
--L["current"] = "Current Profile:"
elseif LOCALE == "frFR" then
L["default"] = "D\195\169faut"
L["intro"] = "Vous pouvez changer le profil actuel afin d'avoir des param\195\168tres diff\195\169rents pour chaque personnage, permettant ainsi d'avoir une configuration tr\195\168s flexible."
L["reset_desc"] = "R\195\169initialise le profil actuel au cas o\195\185 votre configuration est corrompue ou si vous voulez tout simplement faire table rase."
L["reset"] = "R\195\169initialiser le profil"
L["reset_sub"] = "R\195\169initialise le profil actuel avec les param\195\168tres par d\195\169faut."
L["choose_desc"] = "Vous pouvez cr\195\169er un nouveau profil en entrant un nouveau nom dans la bo\195\174te de saisie, ou en choississant un des profils d\195\169j\195\160 existants."
L["new"] = "Nouveau"
L["new_sub"] = "Cr\195\169\195\169e un nouveau profil vierge."
L["choose"] = "Profils existants"
L["choose_sub"] = "Permet de choisir un des profils d\195\169j\195\160 disponibles."
L["copy_desc"] = "Copie les param\195\168tres d'un profil d\195\169j\195\160 existant dans le profil actuellement actif."
L["copy"] = "Copier \195\160 partir de"
L["delete_desc"] = "Supprime les profils existants inutilis\195\169s de la base de donn\195\169es afin de gagner de la place et de nettoyer le fichier SavedVariables."
L["delete"] = "Supprimer un profil"
L["delete_sub"] = "Supprime un profil de la base de donn\195\169es."
L["delete_confirm"] = "Etes-vous s\195\187r de vouloir supprimer le profil s\195\169lectionn\195\169 ?"
L["profiles"] = "Profils"
L["profiles_sub"] = "Gestion des profils"
--L["current"] = "Current Profile:"
elseif LOCALE == "koKR" then
L["default"] = "기본값"
L["intro"] = "모든 캐릭터의 다양한 설정과 사용중인 데이터베이스 프로필, 어느것이던지 매우 다루기 쉽게 바꿀수 있습니다."
L["reset_desc"] = "단순히 다시 새롭게 구성을 원하는 경우, 현재 프로필을 기본값으로 초기화 합니다."
L["reset"] = "프로필 초기화"
L["reset_sub"] = "현재의 프로필을 기본값으로 초기화 합니다"
L["choose_desc"] = "새로운 이름을 입력하거나, 이미 있는 프로필중 하나를 선택하여 새로운 프로필을 만들 수 있습니다."
L["new"] = "새로운 프로필"
L["new_sub"] = "새로운 프로필을 만듭니다."
L["choose"] = "프로필 선택"
L["choose_sub"] = "당신이 현재 이용할수 있는 프로필을 선택합니다."
L["copy_desc"] = "현재 사용중인 프로필에, 선택한 프로필의 설정을 복사합니다."
L["copy"] = "복사"
L["delete_desc"] = "데이터베이스에 사용중이거나 저장된 프로파일 삭제로 SavedVariables 파일의 정리와 공간 절약이 됩니다."
L["delete"] = "프로필 삭제"
L["delete_sub"] = "데이터베이스의 프로필을 삭제합니다."
L["delete_confirm"] = "정말로 선택한 프로필의 삭제를 원하십니까?"
L["profiles"] = "프로필"
L["profiles_sub"] = "프로필 설정"
--L["current"] = "Current Profile:"
elseif LOCALE == "esES" or LOCALE == "esMX" then
L["default"] = "Por defecto"
L["intro"] = "Puedes cambiar el perfil activo de tal manera que cada personaje tenga diferentes configuraciones."
L["reset_desc"] = "Reinicia el perfil actual a los valores por defectos, en caso de que se haya estropeado la configuración o quieras volver a empezar de nuevo."
L["reset"] = "Reiniciar Perfil"
L["reset_sub"] = "Reinicar el perfil actual al de por defecto"
L["choose_desc"] = "Puedes crear un nuevo perfil introduciendo un nombre en el recuadro o puedes seleccionar un perfil de los ya existentes."
L["new"] = "Nuevo"
L["new_sub"] = "Crear un nuevo perfil vacio."
L["choose"] = "Perfiles existentes"
L["choose_sub"] = "Selecciona uno de los perfiles disponibles."
L["copy_desc"] = "Copia los ajustes de un perfil existente al perfil actual."
L["copy"] = "Copiar de"
L["delete_desc"] = "Borra los perfiles existentes y sin uso de la base de datos para ganar espacio y limpiar el archivo SavedVariables."
L["delete"] = "Borrar un Perfil"
L["delete_sub"] = "Borra un perfil de la base de datos."
L["delete_confirm"] = "¿Estas seguro que quieres borrar el perfil seleccionado?"
L["profiles"] = "Perfiles"
L["profiles_sub"] = "Manejar Perfiles"
--L["current"] = "Current Profile:"
elseif LOCALE == "zhTW" then
L["default"] = "預設"
L["intro"] = "你可以選擇一個活動的資料設定檔,這樣你的每個角色就可以擁有不同的設定值,可以給你的插件設定帶來極大的靈活性。"
L["reset_desc"] = "將當前的設定檔恢復到它的預設值,用於你的設定檔損壞,或者你只是想重來的情況。"
L["reset"] = "重置設定檔"
L["reset_sub"] = "將當前的設定檔恢復為預設值"
L["choose_desc"] = "你可以通過在文本框內輸入一個名字創立一個新的設定檔,也可以選擇一個已經存在的設定檔。"
L["new"] = "新建"
L["new_sub"] = "新建一個空的設定檔。"
L["choose"] = "現有的設定檔"
L["choose_sub"] = "從當前可用的設定檔裏面選擇一個。"
L["copy_desc"] = "從當前某個已保存的設定檔複製到當前正使用的設定檔。"
L["copy"] = "複製自"
L["delete_desc"] = "從資料庫裏刪除不再使用的設定檔以節省空間並且清理SavedVariables檔。"
L["delete"] = "刪除一個設定檔"
L["delete_sub"] = "從資料庫裏刪除一個設定檔。"
L["delete_confirm"] = "你確定要刪除所選擇的設定檔嗎?"
L["profiles"] = "設定檔"
L["profiles_sub"] = "管理設定檔"
--L["current"] = "Current Profile:"
elseif LOCALE == "zhCN" then
L["default"] = "默认"
L["intro"] = "你可以选择一个活动的数据配置文件,这样你的每个角色就可以拥有不同的设置值,可以给你的插件配置带来极大的灵活性。"
L["reset_desc"] = "将当前的配置文件恢复到它的默认值,用于你的配置文件损坏,或者你只是想重来的情况。"
L["reset"] = "重置配置文件"
L["reset_sub"] = "将当前的配置文件恢复为默认值"
L["choose_desc"] = "你可以通过在文本框内输入一个名字创立一个新的配置文件,也可以选择一个已经存在的配置文件。"
L["new"] = "新建"
L["new_sub"] = "新建一个空的配置文件。"
L["choose"] = "现有的配置文件"
L["choose_sub"] = "从当前可用的配置文件里面选择一个。"
L["copy_desc"] = "从当前某个已保存的配置文件复制到当前正使用的配置文件。"
L["copy"] = "复制自"
L["delete_desc"] = "从数据库里删除不再使用的配置文件以节省空间并且清理SavedVariables文件。"
L["delete"] = "删除一个配置文件"
L["delete_sub"] = "从数据库里删除一个配置文件。"
L["delete_confirm"] = "你确定要删除所选择的配置文件么?"
L["profiles"] = "配置文件"
L["profiles_sub"] = "管理配置文件"
--L["current"] = "Current Profile:"
elseif LOCALE == "ruRU" then
L["default"] = "По умолчанию"
L["intro"] = "Изменяя активный профиль, вы можете задать различные настройки модификаций для каждого персонажа."
L["reset_desc"] = "Если ваша конфигурации испорчена или если вы хотите настроить всё заново - сбросьте текущий профиль на стандартные значения."
L["reset"] = "Сброс профиля"
L["reset_sub"] = "Сброс текущего профиля на стандартный"
L["choose_desc"] = "Вы можете создать новый профиль, введя название в поле ввода, или выбрать один из уже существующих профилей."
L["new"] = "Новый"
L["new_sub"] = "Создать новый чистый профиль"
L["choose"] = "Существующие профили"
L["choose_sub"] = "Выбор одиного из уже доступных профилей"
L["copy_desc"] = "Скопировать настройки из выбранного профиля в активный."
L["copy"] = "Скопировать из"
L["delete_desc"] = "Удалить существующий и неиспользуемый профиль из БД для сохранения места, и очистить SavedVariables файл."
L["delete"] = "Удалить профиль"
L["delete_sub"] = "Удаление профиля из БД"
L["delete_confirm"] = "Вы уверены, что вы хотите удалить выбранный профиль?"
L["profiles"] = "Профили"
L["profiles_sub"] = "Управление профилями"
--L["current"] = "Current Profile:"
end
local defaultProfiles
local tmpprofiles = {}
-- Get a list of available profiles for the specified database.
-- You can specify which profiles to include/exclude in the list using the two boolean parameters listed below.
-- @param db The db object to retrieve the profiles from
-- @param common If true, getProfileList will add the default profiles to the return list, even if they have not been created yet
-- @param nocurrent If true, then getProfileList will not display the current profile in the list
-- @return Hashtable of all profiles with the internal name as keys and the display name as value.
local function getProfileList(db, common, nocurrent)
local profiles = {}
-- copy existing profiles into the table
local currentProfile = db:GetCurrentProfile()
for i,v in pairs(db:GetProfiles(tmpprofiles)) do
if not (nocurrent and v == currentProfile) then
profiles[v] = v
end
end
-- add our default profiles to choose from ( or rename existing profiles)
for k,v in pairs(defaultProfiles) do
if (common or profiles[k]) and not (nocurrent and k == currentProfile) then
profiles[k] = v
end
end
return profiles
end
--[[
OptionsHandlerPrototype
prototype class for handling the options in a sane way
]]
local OptionsHandlerPrototype = {}
--[[ Reset the profile ]]
function OptionsHandlerPrototype:Reset()
self.db:ResetProfile()
end
--[[ Set the profile to value ]]
function OptionsHandlerPrototype:SetProfile(info, value)
self.db:SetProfile(value)
end
--[[ returns the currently active profile ]]
function OptionsHandlerPrototype:GetCurrentProfile()
return self.db:GetCurrentProfile()
end
--[[
List all active profiles
you can control the output with the .arg variable
currently four modes are supported
(empty) - return all available profiles
"nocurrent" - returns all available profiles except the currently active profile
"common" - returns all avaialble profiles + some commonly used profiles ("char - realm", "realm", "class", "Default")
"both" - common except the active profile
]]
function OptionsHandlerPrototype:ListProfiles(info)
local arg = info.arg
local profiles
if arg == "common" and not self.noDefaultProfiles then
profiles = getProfileList(self.db, true, nil)
elseif arg == "nocurrent" then
profiles = getProfileList(self.db, nil, true)
elseif arg == "both" then -- currently not used
profiles = getProfileList(self.db, (not self.noDefaultProfiles) and true, true)
else
profiles = getProfileList(self.db)
end
return profiles
end
function OptionsHandlerPrototype:HasNoProfiles(info)
local profiles = self:ListProfiles(info)
return ((not next(profiles)) and true or false)
end
--[[ Copy a profile ]]
function OptionsHandlerPrototype:CopyProfile(info, value)
self.db:CopyProfile(value)
end
--[[ Delete a profile from the db ]]
function OptionsHandlerPrototype:DeleteProfile(info, value)
self.db:DeleteProfile(value)
end
--[[ fill defaultProfiles with some generic values ]]
local function generateDefaultProfiles(db)
defaultProfiles = {
["Default"] = L["default"],
[db.keys.char] = db.keys.char,
[db.keys.realm] = db.keys.realm,
[db.keys.class] = UnitClass("player")
}
end
--[[ create and return a handler object for the db, or upgrade it if it already existed ]]
local function getOptionsHandler(db, noDefaultProfiles)
if not defaultProfiles then
generateDefaultProfiles(db)
end
local handler = AceDBOptions.handlers[db] or { db = db, noDefaultProfiles = noDefaultProfiles }
for k,v in pairs(OptionsHandlerPrototype) do
handler[k] = v
end
AceDBOptions.handlers[db] = handler
return handler
end
--[[
the real options table
]]
local optionsTable = {
desc = {
order = 1,
type = "description",
name = L["intro"] .. "\n",
},
descreset = {
order = 9,
type = "description",
name = L["reset_desc"],
},
reset = {
order = 10,
type = "execute",
name = L["reset"],
desc = L["reset_sub"],
func = "Reset",
},
current = {
order = 11,
type = "description",
name = function(info) return L["current"] .. " " .. NORMAL_FONT_COLOR_CODE .. info.handler:GetCurrentProfile() .. FONT_COLOR_CODE_CLOSE end,
width = "default",
},
choosedesc = {
order = 20,
type = "description",
name = "\n" .. L["choose_desc"],
},
new = {
name = L["new"],
desc = L["new_sub"],
type = "input",
order = 30,
get = false,
set = "SetProfile",
},
choose = {
name = L["choose"],
desc = L["choose_sub"],
type = "select",
order = 40,
get = "GetCurrentProfile",
set = "SetProfile",
values = "ListProfiles",
arg = "common",
},
copydesc = {
order = 50,
type = "description",
name = "\n" .. L["copy_desc"],
},
copyfrom = {
order = 60,
type = "select",
name = L["copy"],
desc = L["copy_desc"],
get = false,
set = "CopyProfile",
values = "ListProfiles",
disabled = "HasNoProfiles",
arg = "nocurrent",
},
deldesc = {
order = 70,
type = "description",
name = "\n" .. L["delete_desc"],
},
delete = {
order = 80,
type = "select",
name = L["delete"],
desc = L["delete_sub"],
get = false,
set = "DeleteProfile",
values = "ListProfiles",
disabled = "HasNoProfiles",
arg = "nocurrent",
confirm = true,
confirmText = L["delete_confirm"],
},
}
--- Get/Create a option table that you can use in your addon to control the profiles of AceDB-3.0.
-- @param db The database object to create the options table for.
-- @return The options table to be used in AceConfig-3.0
-- @usage
-- -- Assuming `options` is your top-level options table and `self.db` is your database:
-- options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
function AceDBOptions:GetOptionsTable(db, noDefaultProfiles)
local tbl = AceDBOptions.optionTables[db] or {
type = "group",
name = L["profiles"],
desc = L["profiles_sub"],
}
tbl.handler = getOptionsHandler(db, noDefaultProfiles)
tbl.args = optionsTable
AceDBOptions.optionTables[db] = tbl
return tbl
end
-- upgrade existing tables
for db,tbl in pairs(AceDBOptions.optionTables) do
tbl.handler = getOptionsHandler(db)
tbl.args = optionsTable
end

View 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>

View File

@@ -0,0 +1,805 @@
--- **AceGUI-3.0** provides access to numerous widgets which can be used to create GUIs.
-- AceGUI is used by AceConfigDialog to create the option GUIs, but you can use it by itself
-- to create any custom GUI. There are more extensive examples in the test suite in the Ace3
-- stand-alone distribution.
--
-- **Note**: When using AceGUI-3.0 directly, please do not modify the frames of the widgets directly,
-- as any "unknown" change to the widgets will cause addons that get your widget out of the widget pool
-- to misbehave. If you think some part of a widget should be modifiable, please open a ticket, and we"ll
-- implement a proper API to modify it.
-- @usage
-- local AceGUI = LibStub("AceGUI-3.0")
-- -- Create a container frame
-- local f = AceGUI:Create("Frame")
-- f:SetCallback("OnClose",function(widget) AceGUI:Release(widget) end)
-- f:SetTitle("AceGUI-3.0 Example")
-- f:SetStatusText("Status Bar")
-- f:SetLayout("Flow")
-- -- Create a button
-- local btn = AceGUI:Create("Button")
-- btn:SetWidth(170)
-- btn:SetText("Button !")
-- btn:SetCallback("OnClick", function() print("Click!") end)
-- -- Add the button to the container
-- f:AddChild(btn)
-- @class file
-- @name AceGUI-3.0
-- @release $Id: AceGUI-3.0.lua 924 2010-05-13 15:12:20Z nevcairiel $
local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 33
local AceGUI, oldminor = LibStub:NewLibrary(ACEGUI_MAJOR, ACEGUI_MINOR)
if not AceGUI then return end -- No upgrade needed
-- Lua APIs
local tconcat, tremove, tinsert = table.concat, table.remove, table.insert
local select, pairs, next, type = select, pairs, next, type
local error, assert, loadstring = error, assert, loadstring
local setmetatable, rawget, rawset = setmetatable, rawget, rawset
local math_max = math.max
-- WoW APIs
local UIParent = UIParent
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: geterrorhandler, LibStub
--local con = LibStub("AceConsole-3.0",true)
AceGUI.WidgetRegistry = AceGUI.WidgetRegistry or {}
AceGUI.LayoutRegistry = AceGUI.LayoutRegistry or {}
AceGUI.WidgetBase = AceGUI.WidgetBase or {}
AceGUI.WidgetContainerBase = AceGUI.WidgetContainerBase or {}
AceGUI.WidgetVersions = AceGUI.WidgetVersions or {}
-- local upvalues
local WidgetRegistry = AceGUI.WidgetRegistry
local LayoutRegistry = AceGUI.LayoutRegistry
local WidgetVersions = AceGUI.WidgetVersions
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = ...
local method, ARGS
local function call() return method(ARGS) end
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = ...
return xpcall(call, eh)
end
return dispatch
]]
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = code:gsub("ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
Dispatchers[0] = function(func)
return xpcall(func, errorhandler)
end
local function safecall(func, ...)
return Dispatchers[select("#", ...)](func, ...)
end
-- Recycling functions
local newWidget, delWidget
do
-- Version Upgrade in Minor 29
-- Internal Storage of the objects changed, from an array table
-- to a hash table, and additionally we introduced versioning on
-- the widgets which would discard all widgets from a pre-29 version
-- anyway, so we just clear the storage now, and don't try to
-- convert the storage tables to the new format.
-- This should generally not cause *many* widgets to end up in trash,
-- since once dialogs are opened, all addons should be loaded already
-- and AceGUI should be on the latest version available on the users
-- setup.
-- -- nevcairiel - Nov 2nd, 2009
if oldminor and oldminor < 29 and AceGUI.objPools then
AceGUI.objPools = nil
end
AceGUI.objPools = AceGUI.objPools or {}
local objPools = AceGUI.objPools
--Returns a new instance, if none are available either returns a new table or calls the given contructor
function newWidget(type)
if not WidgetRegistry[type] then
error("Attempt to instantiate unknown widget type", 2)
end
if not objPools[type] then
objPools[type] = {}
end
local newObj = next(objPools[type])
if not newObj then
newObj = WidgetRegistry[type]()
newObj.AceGUIWidgetVersion = WidgetVersions[type]
else
objPools[type][newObj] = nil
-- if the widget is older then the latest, don't even try to reuse it
-- just forget about it, and grab a new one.
if not newObj.AceGUIWidgetVersion or newObj.AceGUIWidgetVersion < WidgetVersions[type] then
return newWidget(type)
end
end
return newObj
end
-- Releases an instance to the Pool
function delWidget(obj,type)
if not objPools[type] then
objPools[type] = {}
end
if objPools[type][obj] then
error("Attempt to Release Widget that is already released", 2)
end
objPools[type][obj] = true
end
end
-------------------
-- API Functions --
-------------------
-- Gets a widget Object
--- Create a new Widget of the given type.
-- This function will instantiate a new widget (or use one from the widget pool), and call the
-- OnAcquire function on it, before returning.
-- @param type The type of the widget.
-- @return The newly created widget.
function AceGUI:Create(type)
if WidgetRegistry[type] then
local widget = newWidget(type)
if rawget(widget, "Acquire") then
widget.OnAcquire = widget.Acquire
widget.Acquire = nil
elseif rawget(widget, "Aquire") then
widget.OnAcquire = widget.Aquire
widget.Aquire = nil
end
if rawget(widget, "Release") then
widget.OnRelease = rawget(widget, "Release")
widget.Release = nil
end
if widget.OnAcquire then
widget:OnAcquire()
else
error(("Widget type %s doesn't supply an OnAcquire Function"):format(type))
end
-- Set the default Layout ("List")
safecall(widget.SetLayout, widget, "List")
safecall(widget.ResumeLayout, widget)
return widget
end
end
--- Releases a widget Object.
-- This function calls OnRelease on the widget and places it back in the widget pool.
-- Any data on the widget is being erased, and the widget will be hidden.\\
-- If this widget is a Container-Widget, all of its Child-Widgets will be releases as well.
-- @param widget The widget to release
function AceGUI:Release(widget)
safecall(widget.PauseLayout, widget)
widget:Fire("OnRelease")
safecall(widget.ReleaseChildren, widget)
if widget.OnRelease then
widget:OnRelease()
-- else
-- error(("Widget type %s doesn't supply an OnRelease Function"):format(widget.type))
end
for k in pairs(widget.userdata) do
widget.userdata[k] = nil
end
for k in pairs(widget.events) do
widget.events[k] = nil
end
widget.width = nil
widget.relWidth = nil
widget.height = nil
widget.relHeight = nil
widget.noAutoHeight = nil
widget.frame:ClearAllPoints()
widget.frame:Hide()
widget.frame:SetParent(UIParent)
widget.frame.width = nil
widget.frame.height = nil
if widget.content then
widget.content.width = nil
widget.content.height = nil
end
delWidget(widget, widget.type)
end
-----------
-- Focus --
-----------
--- Called when a widget has taken focus.
-- e.g. Dropdowns opening, Editboxes gaining kb focus
-- @param widget The widget that should be focused
function AceGUI:SetFocus(widget)
if self.FocusedWidget and self.FocusedWidget ~= widget then
safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget)
end
self.FocusedWidget = widget
end
--- Called when something has happened that could cause widgets with focus to drop it
-- e.g. titlebar of a frame being clicked
function AceGUI:ClearFocus()
if self.FocusedWidget then
safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget)
self.FocusedWidget = nil
end
end
-------------
-- Widgets --
-------------
--[[
Widgets must provide the following functions
OnAcquire() - Called when the object is acquired, should set everything to a default hidden state
And the following members
frame - the frame or derivitive object that will be treated as the widget for size and anchoring purposes
type - the type of the object, same as the name given to :RegisterWidget()
Widgets contain a table called userdata, this is a safe place to store data associated with the wigdet
It will be cleared automatically when a widget is released
Placing values directly into a widget object should be avoided
If the Widget can act as a container for other Widgets the following
content - frame or derivitive that children will be anchored to
The Widget can supply the following Optional Members
:OnRelease() - Called when the object is Released, should remove any additional anchors and clear any data
:OnWidthSet(width) - Called when the width of the widget is changed
:OnHeightSet(height) - Called when the height of the widget is changed
Widgets should not use the OnSizeChanged events of thier frame or content members, use these methods instead
AceGUI already sets a handler to the event
:LayoutFinished(width, height) - called after a layout has finished, the width and height will be the width and height of the
area used for controls. These can be nil if the layout used the existing size to layout the controls.
]]
--------------------------
-- Widget Base Template --
--------------------------
do
local WidgetBase = AceGUI.WidgetBase
WidgetBase.SetParent = function(self, parent)
local frame = self.frame
frame:SetParent(nil)
frame:SetParent(parent.content)
self.parent = parent
end
WidgetBase.SetCallback = function(self, name, func)
if type(func) == "function" then
self.events[name] = func
end
end
WidgetBase.Fire = function(self, name, ...)
if self.events[name] then
local success, ret = safecall(self.events[name], self, name, ...)
if success then
return ret
end
end
end
WidgetBase.SetWidth = function(self, width)
self.frame:SetWidth(width)
self.frame.width = width
if self.OnWidthSet then
self:OnWidthSet(width)
end
end
WidgetBase.SetRelativeWidth = function(self, width)
if width <= 0 or width > 1 then
error(":SetRelativeWidth(width): Invalid relative width.", 2)
end
self.relWidth = width
self.width = "relative"
end
WidgetBase.SetHeight = function(self, height)
self.frame:SetHeight(height)
self.frame.height = height
if self.OnHeightSet then
self:OnHeightSet(height)
end
end
--[[ WidgetBase.SetRelativeHeight = function(self, height)
if height <= 0 or height > 1 then
error(":SetRelativeHeight(height): Invalid relative height.", 2)
end
self.relHeight = height
self.height = "relative"
end ]]
WidgetBase.IsVisible = function(self)
return self.frame:IsVisible()
end
WidgetBase.IsShown= function(self)
return self.frame:IsShown()
end
WidgetBase.Release = function(self)
AceGUI:Release(self)
end
WidgetBase.SetPoint = function(self, ...)
return self.frame:SetPoint(...)
end
WidgetBase.ClearAllPoints = function(self)
return self.frame:ClearAllPoints()
end
WidgetBase.GetNumPoints = function(self)
return self.frame:GetNumPoints()
end
WidgetBase.GetPoint = function(self, ...)
return self.frame:GetPoint(...)
end
WidgetBase.GetUserDataTable = function(self)
return self.userdata
end
WidgetBase.SetUserData = function(self, key, value)
self.userdata[key] = value
end
WidgetBase.GetUserData = function(self, key)
return self.userdata[key]
end
WidgetBase.IsFullHeight = function(self)
return self.height == "fill"
end
WidgetBase.SetFullHeight = function(self, isFull)
if isFull then
self.height = "fill"
else
self.height = nil
end
end
WidgetBase.IsFullWidth = function(self)
return self.width == "fill"
end
WidgetBase.SetFullWidth = function(self, isFull)
if isFull then
self.width = "fill"
else
self.width = nil
end
end
-- local function LayoutOnUpdate(this)
-- this:SetScript("OnUpdate",nil)
-- this.obj:PerformLayout()
-- end
local WidgetContainerBase = AceGUI.WidgetContainerBase
WidgetContainerBase.PauseLayout = function(self)
self.LayoutPaused = true
end
WidgetContainerBase.ResumeLayout = function(self)
self.LayoutPaused = nil
end
WidgetContainerBase.PerformLayout = function(self)
if self.LayoutPaused then
return
end
safecall(self.LayoutFunc, self.content, self.children)
end
--call this function to layout, makes sure layed out objects get a frame to get sizes etc
WidgetContainerBase.DoLayout = function(self)
self:PerformLayout()
-- if not self.parent then
-- self.frame:SetScript("OnUpdate", LayoutOnUpdate)
-- end
end
WidgetContainerBase.AddChild = function(self, child, beforeWidget)
if beforeWidget then
local siblingIndex = 1
for _, widget in pairs(self.children) do
if widget == beforeWidget then
break
end
siblingIndex = siblingIndex + 1
end
tinsert(self.children, siblingIndex, child)
else
tinsert(self.children, child)
end
child:SetParent(self)
child.frame:Show()
self:DoLayout()
end
WidgetContainerBase.AddChildren = function(self, ...)
for i = 1, select("#", ...) do
local child = select(i, ...)
tinsert(self.children, child)
child:SetParent(self)
child.frame:Show()
end
self:DoLayout()
end
WidgetContainerBase.ReleaseChildren = function(self)
local children = self.children
for i = 1,#children do
AceGUI:Release(children[i])
children[i] = nil
end
end
WidgetContainerBase.SetLayout = function(self, Layout)
self.LayoutFunc = AceGUI:GetLayout(Layout)
end
WidgetContainerBase.SetAutoAdjustHeight = function(self, adjust)
if adjust then
self.noAutoHeight = nil
else
self.noAutoHeight = true
end
end
local function FrameResize(this)
local self = this.obj
if this:GetWidth() and this:GetHeight() then
if self.OnWidthSet then
self:OnWidthSet(this:GetWidth())
end
if self.OnHeightSet then
self:OnHeightSet(this:GetHeight())
end
end
end
local function ContentResize(this)
if this:GetWidth() and this:GetHeight() then
this.width = this:GetWidth()
this.height = this:GetHeight()
this.obj:DoLayout()
end
end
setmetatable(WidgetContainerBase, {__index=WidgetBase})
--One of these function should be called on each Widget Instance as part of its creation process
--- Register a widget-class as a container for newly created widgets.
-- @param widget The widget class
function AceGUI:RegisterAsContainer(widget)
widget.children = {}
widget.userdata = {}
widget.events = {}
widget.base = WidgetContainerBase
widget.content.obj = widget
widget.frame.obj = widget
widget.content:SetScript("OnSizeChanged", ContentResize)
widget.frame:SetScript("OnSizeChanged", FrameResize)
setmetatable(widget, {__index = WidgetContainerBase})
widget:SetLayout("List")
return widget
end
--- Register a widget-class as a widget.
-- @param widget The widget class
function AceGUI:RegisterAsWidget(widget)
widget.userdata = {}
widget.events = {}
widget.base = WidgetBase
widget.frame.obj = widget
widget.frame:SetScript("OnSizeChanged", FrameResize)
setmetatable(widget, {__index = WidgetBase})
return widget
end
end
------------------
-- Widget API --
------------------
--- Registers a widget Constructor, this function returns a new instance of the Widget
-- @param Name The name of the widget
-- @param Constructor The widget constructor function
-- @param Version The version of the widget
function AceGUI:RegisterWidgetType(Name, Constructor, Version)
assert(type(Constructor) == "function")
assert(type(Version) == "number")
local oldVersion = WidgetVersions[Name]
if oldVersion and oldVersion >= Version then return end
WidgetVersions[Name] = Version
WidgetRegistry[Name] = Constructor
end
--- Registers a Layout Function
-- @param Name The name of the layout
-- @param LayoutFunc Reference to the layout function
function AceGUI:RegisterLayout(Name, LayoutFunc)
assert(type(LayoutFunc) == "function")
if type(Name) == "string" then
Name = Name:upper()
end
LayoutRegistry[Name] = LayoutFunc
end
--- Get a Layout Function from the registry
-- @param Name The name of the layout
function AceGUI:GetLayout(Name)
if type(Name) == "string" then
Name = Name:upper()
end
return LayoutRegistry[Name]
end
AceGUI.counts = AceGUI.counts or {}
--- A type-based counter to count the number of widgets created.
-- This is used by widgets that require a named frame, e.g. when a Blizzard
-- Template requires it.
-- @param type The widget type
function AceGUI:GetNextWidgetNum(type)
if not self.counts[type] then
self.counts[type] = 0
end
self.counts[type] = self.counts[type] + 1
return self.counts[type]
end
--- Return the number of created widgets for this type.
-- In contrast to GetNextWidgetNum, the number is not incremented.
-- @param type The widget type
function AceGUI:GetWidgetCount(type)
return self.counts[type] or 0
end
--- Return the version of the currently registered widget type.
-- @param type The widget type
function AceGUI:GetWidgetVersion(type)
return WidgetVersions[type]
end
-------------
-- Layouts --
-------------
--[[
A Layout is a func that takes 2 parameters
content - the frame that widgets will be placed inside
children - a table containing the widgets to layout
]]
-- Very simple Layout, Children are stacked on top of each other down the left side
AceGUI:RegisterLayout("List",
function(content, children)
local height = 0
local width = content.width or content:GetWidth() or 0
for i = 1, #children do
local child = children[i]
local frame = child.frame
frame:ClearAllPoints()
frame:Show()
if i == 1 then
frame:SetPoint("TOPLEFT", content)
else
frame:SetPoint("TOPLEFT", children[i-1].frame, "BOTTOMLEFT")
end
if child.width == "fill" then
child:SetWidth(width)
frame:SetPoint("RIGHT", content)
if child.DoLayout then
child:DoLayout()
end
elseif child.width == "relative" then
child:SetWidth(width * child.relWidth)
if child.DoLayout then
child:DoLayout()
end
end
height = height + (frame.height or frame:GetHeight() or 0)
end
safecall(content.obj.LayoutFinished, content.obj, nil, height)
end)
-- A single control fills the whole content area
AceGUI:RegisterLayout("Fill",
function(content, children)
if children[1] then
children[1]:SetWidth(content:GetWidth() or 0)
children[1]:SetHeight(content:GetHeight() or 0)
children[1].frame:SetAllPoints(content)
children[1].frame:Show()
safecall(content.obj.LayoutFinished, content.obj, nil, children[1].frame:GetHeight())
end
end)
AceGUI:RegisterLayout("Flow",
function(content, children)
--used height so far
local height = 0
--width used in the current row
local usedwidth = 0
--height of the current row
local rowheight = 0
local rowoffset = 0
local lastrowoffset
local width = content.width or content:GetWidth() or 0
--control at the start of the row
local rowstart
local rowstartoffset
local lastrowstart
local isfullheight
local frameoffset
local lastframeoffset
local oversize
for i = 1, #children do
local child = children[i]
oversize = nil
local frame = child.frame
local frameheight = frame.height or frame:GetHeight() or 0
local framewidth = frame.width or frame:GetWidth() or 0
lastframeoffset = frameoffset
-- HACK: Why did we set a frameoffset of (frameheight / 2) ?
-- That was moving all widgets half the widgets size down, is that intended?
-- Actually, it seems to be neccessary for many cases, we'll leave it in for now.
-- If widgets seem to anchor weirdly with this, provide a valid alignoffset for them.
-- TODO: Investigate moar!
frameoffset = child.alignoffset or (frameheight / 2)
if child.width == "relative" then
framewidth = width * child.relWidth
end
frame:Show()
frame:ClearAllPoints()
if i == 1 then
-- anchor the first control to the top left
frame:SetPoint("TOPLEFT", content)
rowheight = frameheight
rowoffset = frameoffset
rowstart = frame
rowstartoffset = frameoffset
usedwidth = framewidth
if usedwidth > width then
oversize = true
end
else
-- if there isn't available width for the control start a new row
-- if a control is "fill" it will be on a row of its own full width
if usedwidth == 0 or ((framewidth) + usedwidth > width) or child.width == "fill" then
if isfullheight then
-- a previous row has already filled the entire height, there's nothing we can usefully do anymore
-- (maybe error/warn about this?)
break
end
--anchor the previous row, we will now know its height and offset
rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3))
height = height + rowheight + 3
--save this as the rowstart so we can anchor it after the row is complete and we have the max height and offset of controls in it
rowstart = frame
rowstartoffset = frameoffset
rowheight = frameheight
rowoffset = frameoffset
usedwidth = framewidth
if usedwidth > width then
oversize = true
end
-- put the control on the current row, adding it to the width and checking if the height needs to be increased
else
--handles cases where the new height is higher than either control because of the offsets
--math.max(rowheight-rowoffset+frameoffset, frameheight-frameoffset+rowoffset)
--offset is always the larger of the two offsets
rowoffset = math_max(rowoffset, frameoffset)
rowheight = math_max(rowheight, rowoffset + (frameheight / 2))
frame:SetPoint("TOPLEFT", children[i-1].frame, "TOPRIGHT", 0, frameoffset - lastframeoffset)
usedwidth = framewidth + usedwidth
end
end
if child.width == "fill" then
child:SetWidth(width)
frame:SetPoint("RIGHT", content)
usedwidth = 0
rowstart = frame
rowstartoffset = frameoffset
if child.DoLayout then
child:DoLayout()
end
rowheight = frame.height or frame:GetHeight() or 0
rowoffset = child.alignoffset or (rowheight / 2)
rowstartoffset = rowoffset
elseif child.width == "relative" then
child:SetWidth(width * child.relWidth)
if child.DoLayout then
child:DoLayout()
end
elseif oversize then
if width > 1 then
frame:SetPoint("RIGHT", content)
end
end
if child.height == "fill" then
frame:SetPoint("BOTTOM", content)
isfullheight = true
end
end
--anchor the last row, if its full height needs a special case since its height has just been changed by the anchor
if isfullheight then
rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -height)
elseif rowstart then
rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3))
end
height = height + rowheight + 3
safecall(content.obj.LayoutFinished, content.obj, nil, height)
end)

View File

@@ -0,0 +1,28 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="AceGUI-3.0.lua"/>
<!-- Container -->
<Script file="widgets\AceGUIContainer-BlizOptionsGroup.lua"/>
<Script file="widgets\AceGUIContainer-DropDownGroup.lua"/>
<Script file="widgets\AceGUIContainer-Frame.lua"/>
<Script file="widgets\AceGUIContainer-InlineGroup.lua"/>
<Script file="widgets\AceGUIContainer-ScrollFrame.lua"/>
<Script file="widgets\AceGUIContainer-SimpleGroup.lua"/>
<Script file="widgets\AceGUIContainer-TabGroup.lua"/>
<Script file="widgets\AceGUIContainer-TreeGroup.lua"/>
<Script file="widgets\AceGUIContainer-Window.lua"/>
<!-- Widgets -->
<Script file="widgets\AceGUIWidget-Button.lua"/>
<Script file="widgets\AceGUIWidget-CheckBox.lua"/>
<Script file="widgets\AceGUIWidget-ColorPicker.lua"/>
<Script file="widgets\AceGUIWidget-DropDown.lua"/>
<Script file="widgets\AceGUIWidget-DropDown-Items.lua"/>
<Script file="widgets\AceGUIWidget-EditBox.lua"/>
<Script file="widgets\AceGUIWidget-Heading.lua"/>
<Script file="widgets\AceGUIWidget-Icon.lua"/>
<Script file="widgets\AceGUIWidget-InteractiveLabel.lua"/>
<Script file="widgets\AceGUIWidget-Keybinding.lua"/>
<Script file="widgets\AceGUIWidget-Label.lua"/>
<Script file="widgets\AceGUIWidget-MultiLineEditBox.lua"/>
<Script file="widgets\AceGUIWidget-Slider.lua"/>
</Ui>

View File

@@ -0,0 +1,133 @@
--[[-----------------------------------------------------------------------------
BlizOptionsGroup Container
Simple container widget for the integration of AceGUI into the Blizzard Interface Options
-------------------------------------------------------------------------------]]
local Type, Version = "BlizOptionsGroup", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local pairs = pairs
-- WoW APIs
local CreateFrame = CreateFrame
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function OnShow(frame)
frame.obj:Fire("OnShow")
end
local function OnHide(frame)
frame.obj:Fire("OnHide")
end
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function okay(frame)
frame.obj:Fire("okay")
end
local function cancel(frame)
frame.obj:Fire("cancel")
end
local function defaults(frame)
frame.obj:Fire("defaults")
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetName()
self:SetTitle()
end,
-- ["OnRelease"] = nil,
["OnWidthSet"] = function(self, width)
local content = self.content
local contentwidth = width - 63
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
end,
["OnHeightSet"] = function(self, height)
local content = self.content
local contentheight = height - 26
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end,
["SetName"] = function(self, name, parent)
self.frame.name = name
self.frame.parent = parent
end,
["SetTitle"] = function(self, title)
local content = self.content
content:ClearAllPoints()
if not title or title == "" then
content:SetPoint("TOPLEFT", 10, -10)
self.label:SetText("")
else
content:SetPoint("TOPLEFT", 10, -40)
self.label:SetText(title)
end
content:SetPoint("BOTTOMRIGHT", -10, 10)
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Frame")
frame:Hide()
-- support functions for the Blizzard Interface Options
frame.okay = okay
frame.cancel = cancel
frame.defaults = defaults
frame:SetScript("OnHide", OnHide)
frame:SetScript("OnShow", OnShow)
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
label:SetPoint("TOPLEFT", 10, -15)
label:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", 10, -45)
label:SetJustifyH("LEFT")
label:SetJustifyV("TOP")
--Container Support
local content = CreateFrame("Frame", nil, frame)
content:SetPoint("TOPLEFT", 10, -10)
content:SetPoint("BOTTOMRIGHT", -10, 10)
local widget = {
label = label,
frame = frame,
content = content,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
return AceGUI:RegisterAsContainer(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,157 @@
--[[-----------------------------------------------------------------------------
DropdownGroup Container
Container controlled by a dropdown on the top.
-------------------------------------------------------------------------------]]
local Type, Version = "DropdownGroup", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local assert, pairs, type = assert, pairs, type
-- WoW APIs
local CreateFrame = CreateFrame
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
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
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self.dropdown:SetText("")
self:SetDropdownWidth(200)
self:SetTitle("")
end,
["OnRelease"] = function(self)
self.dropdown.list = nil
self.status = nil
for k in pairs(self.localstatus) do
self.localstatus[k] = nil
end
end,
["SetTitle"] = function(self, title)
self.titletext:SetText(title)
self.dropdown.frame:ClearAllPoints()
if title and title ~= "" then
self.dropdown.frame:SetPoint("TOPRIGHT", -2, 0)
else
self.dropdown.frame:SetPoint("TOPLEFT", -1, 0)
end
end,
["SetGroupList"] = function(self,list)
self.dropdown:SetList(list)
end,
["SetStatusTable"] = function(self, status)
assert(type(status) == "table")
self.status = status
end,
["SetGroup"] = function(self,group)
self.dropdown:SetValue(group)
local status = self.status or self.localstatus
status.selected = group
self:Fire("OnGroupSelected", group)
end,
["OnWidthSet"] = function(self, width)
local content = self.content
local contentwidth = width - 26
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
end,
["OnHeightSet"] = function(self, height)
local content = self.content
local contentheight = height - 63
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end,
["LayoutFinished"] = function(self, width, height)
self:SetHeight((height or 0) + 63)
end,
["SetDropdownWidth"] = function(self, width)
self.dropdown:SetWidth(width)
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local PaneBackdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 3, right = 3, top = 5, bottom = 3 }
}
local function Constructor()
local frame = CreateFrame("Frame")
frame:SetHeight(100)
frame:SetWidth(100)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
local titletext = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
titletext:SetPoint("TOPLEFT", 4, -5)
titletext:SetPoint("TOPRIGHT", -4, -5)
titletext:SetJustifyH("LEFT")
titletext:SetHeight(18)
local dropdown = AceGUI:Create("Dropdown")
dropdown.frame:SetParent(frame)
dropdown.frame:SetFrameLevel(dropdown.frame:GetFrameLevel() + 2)
dropdown:SetCallback("OnValueChanged", SelectedGroup)
dropdown.frame:SetPoint("TOPLEFT", -1, 0)
dropdown.frame:Show()
dropdown:SetLabel("")
local border = CreateFrame("Frame", nil, frame)
border:SetPoint("TOPLEFT", 0, -26)
border:SetPoint("BOTTOMRIGHT", 0, 3)
border:SetBackdrop(PaneBackdrop)
border:SetBackdropColor(0.1,0.1,0.1,0.5)
border:SetBackdropBorderColor(0.4,0.4,0.4)
--Container Support
local content = CreateFrame("Frame", nil, border)
content:SetPoint("TOPLEFT", 10, -10)
content:SetPoint("BOTTOMRIGHT", -10, 10)
local widget = {
frame = frame,
localstatus = {},
titletext = titletext,
dropdown = dropdown,
border = border,
content = content,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
dropdown.parentgroup = widget
return AceGUI:RegisterAsContainer(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,298 @@
--[[-----------------------------------------------------------------------------
Frame Container
-------------------------------------------------------------------------------]]
local Type, Version = "Frame", 21
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local pairs, assert, type = pairs, assert, type
local wipe = table.wipe
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame, UIParent = CreateFrame, UIParent
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: CLOSE
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Button_OnClick(frame)
PlaySound("gsTitleOptionExit")
frame.obj:Hide()
end
local function Frame_OnClose(frame)
frame.obj:Fire("OnClose")
end
local function Frame_OnMouseDown(frame)
AceGUI:ClearFocus()
end
local function Title_OnMouseDown(frame)
frame:GetParent():StartMoving()
AceGUI:ClearFocus()
end
local function MoverSizer_OnMouseUp(mover)
local frame = mover:GetParent()
frame:StopMovingOrSizing()
local self = frame.obj
local status = self.status or self.localstatus
status.width = frame:GetWidth()
status.height = frame:GetHeight()
status.top = frame:GetTop()
status.left = frame:GetLeft()
end
local function SizerSE_OnMouseDown(frame)
frame:GetParent():StartSizing("BOTTOMRIGHT")
AceGUI:ClearFocus()
end
local function SizerS_OnMouseDown(frame)
frame:GetParent():StartSizing("BOTTOM")
AceGUI:ClearFocus()
end
local function SizerE_OnMouseDown(frame)
frame:GetParent():StartSizing("RIGHT")
AceGUI:ClearFocus()
end
local function StatusBar_OnEnter(frame)
frame.obj:Fire("OnEnterStatusBar")
end
local function StatusBar_OnLeave(frame)
frame.obj:Fire("OnLeaveStatusBar")
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self.frame:SetParent(UIParent)
self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
self:SetTitle()
self:SetStatusText()
self:ApplyStatus()
self:Show()
end,
["OnRelease"] = function(self)
self.status = nil
wipe(self.localstatus)
end,
["OnWidthSet"] = function(self, width)
local content = self.content
local contentwidth = width - 34
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
end,
["OnHeightSet"] = function(self, height)
local content = self.content
local contentheight = height - 57
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end,
["SetTitle"] = function(self, title)
self.titletext:SetText(title)
end,
["SetStatusText"] = function(self, text)
self.statustext:SetText(text)
end,
["Hide"] = function(self)
self.frame:Hide()
end,
["Show"] = function(self)
self.frame:Show()
end,
-- called to set an external table to store status in
["SetStatusTable"] = function(self, status)
assert(type(status) == "table")
self.status = status
self:ApplyStatus()
end,
["ApplyStatus"] = function(self)
local status = self.status or self.localstatus
local frame = self.frame
self:SetWidth(status.width or 700)
self:SetHeight(status.height or 500)
frame:ClearAllPoints()
if status.top and status.left then
frame:SetPoint("TOP", UIParent, "BOTTOM", 0, status.top)
frame:SetPoint("LEFT", UIParent, "LEFT", status.left, 0)
else
frame:SetPoint("CENTER")
end
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local FrameBackdrop = {
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
tile = true, tileSize = 32, edgeSize = 32,
insets = { left = 8, right = 8, top = 8, bottom = 8 }
}
local PaneBackdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 3, right = 3, top = 5, bottom = 3 }
}
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:Hide()
frame:EnableMouse(true)
frame:SetMovable(true)
frame:SetResizable(true)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
frame:SetBackdrop(FrameBackdrop)
frame:SetBackdropColor(0, 0, 0, 1)
frame:SetMinResize(400, 200)
frame:SetToplevel(true)
frame:SetScript("OnHide", Frame_OnClose)
frame:SetScript("OnMouseDown", Frame_OnMouseDown)
local closebutton = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
closebutton:SetScript("OnClick", Button_OnClick)
closebutton:SetPoint("BOTTOMRIGHT", -27, 17)
closebutton:SetHeight(20)
closebutton:SetWidth(100)
closebutton:SetText(CLOSE)
local statusbg = CreateFrame("Button", nil, frame)
statusbg:SetPoint("BOTTOMLEFT", 15, 15)
statusbg:SetPoint("BOTTOMRIGHT", -132, 15)
statusbg:SetHeight(24)
statusbg:SetBackdrop(PaneBackdrop)
statusbg:SetBackdropColor(0.1,0.1,0.1)
statusbg:SetBackdropBorderColor(0.4,0.4,0.4)
statusbg:SetScript("OnEnter", StatusBar_OnEnter)
statusbg:SetScript("OnLeave", StatusBar_OnLeave)
local statustext = statusbg:CreateFontString(nil, "OVERLAY", "GameFontNormal")
statustext:SetPoint("TOPLEFT", 7, -2)
statustext:SetPoint("BOTTOMRIGHT", -7, 2)
statustext:SetHeight(20)
statustext:SetJustifyH("LEFT")
statustext:SetText("")
local titlebg = frame:CreateTexture(nil, "OVERLAY")
titlebg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
titlebg:SetTexCoord(0.31, 0.67, 0, 0.63)
titlebg:SetPoint("TOP", 0, 12)
titlebg:SetWidth(100)
titlebg:SetHeight(40)
local title = CreateFrame("Frame", nil, frame)
title:EnableMouse(true)
title:SetScript("OnMouseDown", Title_OnMouseDown)
title:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
title:SetAllPoints(titlebg)
local titletext = title:CreateFontString(nil, "OVERLAY", "GameFontNormal")
titletext:SetPoint("TOP", titlebg, "TOP", 0, -14)
local titlebg_l = frame:CreateTexture(nil, "OVERLAY")
titlebg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
titlebg_l:SetTexCoord(0.21, 0.31, 0, 0.63)
titlebg_l:SetPoint("RIGHT", titlebg, "LEFT")
titlebg_l:SetWidth(30)
titlebg_l:SetHeight(40)
local titlebg_r = frame:CreateTexture(nil, "OVERLAY")
titlebg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
titlebg_r:SetTexCoord(0.67, 0.77, 0, 0.63)
titlebg_r:SetPoint("LEFT", titlebg, "RIGHT")
titlebg_r:SetWidth(30)
titlebg_r:SetHeight(40)
local sizer_se = CreateFrame("Frame", nil, frame)
sizer_se:SetPoint("BOTTOMRIGHT")
sizer_se:SetWidth(25)
sizer_se:SetHeight(25)
sizer_se:EnableMouse()
sizer_se:SetScript("OnMouseDown",SizerSE_OnMouseDown)
sizer_se:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
local line1 = sizer_se:CreateTexture(nil, "BACKGROUND")
line1:SetWidth(14)
line1:SetHeight(14)
line1:SetPoint("BOTTOMRIGHT", -8, 8)
line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
local x = 0.1 * 14/17
line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
local line2 = sizer_se:CreateTexture(nil, "BACKGROUND")
line2:SetWidth(8)
line2:SetHeight(8)
line2:SetPoint("BOTTOMRIGHT", -8, 8)
line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
local x = 0.1 * 8/17
line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
local sizer_s = CreateFrame("Frame", nil, frame)
sizer_s:SetPoint("BOTTOMRIGHT", -25, 0)
sizer_s:SetPoint("BOTTOMLEFT")
sizer_s:SetHeight(25)
sizer_s:EnableMouse(true)
sizer_s:SetScript("OnMouseDown", SizerS_OnMouseDown)
sizer_s:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
local sizer_e = CreateFrame("Frame", nil, frame)
sizer_e:SetPoint("BOTTOMRIGHT", 0, 25)
sizer_e:SetPoint("TOPRIGHT")
sizer_e:SetWidth(25)
sizer_e:EnableMouse(true)
sizer_e:SetScript("OnMouseDown", SizerE_OnMouseDown)
sizer_e:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
--Container Support
local content = CreateFrame("Frame", nil, frame)
content:SetPoint("TOPLEFT", 17, -27)
content:SetPoint("BOTTOMRIGHT", -17, 40)
local widget = {
localstatus = {},
titletext = titletext,
statustext = statustext,
content = content,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
closebutton.obj, statusbg.obj = widget, widget
return AceGUI:RegisterAsContainer(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,102 @@
--[[-----------------------------------------------------------------------------
InlineGroup Container
Simple container widget that creates a visible "box" with an optional title.
-------------------------------------------------------------------------------]]
local Type, Version = "InlineGroup", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local pairs = pairs
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetWidth(300)
self:SetHeight(100)
end,
-- ["OnRelease"] = nil,
["SetTitle"] = function(self,title)
self.titletext:SetText(title)
end,
["LayoutFinished"] = function(self, width, height)
if self.noAutoHeight then return end
self:SetHeight((height or 0) + 40)
end,
["OnWidthSet"] = function(self, width)
local content = self.content
local contentwidth = width - 20
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
end,
["OnHeightSet"] = function(self, height)
local content = self.content
local contentheight = height - 20
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local PaneBackdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 3, right = 3, top = 5, bottom = 3 }
}
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
local titletext = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
titletext:SetPoint("TOPLEFT", 14, 0)
titletext:SetPoint("TOPRIGHT", -14, 0)
titletext:SetJustifyH("LEFT")
titletext:SetHeight(18)
local border = CreateFrame("Frame", nil, frame)
border:SetPoint("TOPLEFT", 0, -17)
border:SetPoint("BOTTOMRIGHT", -1, 3)
border:SetBackdrop(PaneBackdrop)
border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
border:SetBackdropBorderColor(0.4, 0.4, 0.4)
--Container Support
local content = CreateFrame("Frame", nil, border)
content:SetPoint("TOPLEFT", 10, -10)
content:SetPoint("BOTTOMRIGHT", -10, 10)
local widget = {
frame = frame,
content = content,
titletext = titletext,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
return AceGUI:RegisterAsContainer(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,203 @@
--[[-----------------------------------------------------------------------------
ScrollFrame Container
Plain container that scrolls its content and doesn't grow in height.
-------------------------------------------------------------------------------]]
local Type, Version = "ScrollFrame", 21
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local pairs, assert, type = pairs, assert, type
local min, max, floor, abs = math.min, math.max, math.floor, math.abs
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function FixScrollOnUpdate(frame)
frame:SetScript("OnUpdate", nil)
frame.obj:FixScroll()
end
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function ScrollFrame_OnMouseWheel(frame, value)
frame.obj:MoveScroll(value)
end
local function ScrollFrame_OnSizeChanged(frame)
frame:SetScript("OnUpdate", FixScrollOnUpdate)
end
local function ScrollBar_OnScrollValueChanged(frame, value)
frame.obj:SetScroll(value)
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetScroll(0)
end,
["OnRelease"] = function(self)
self.status = nil
for k in pairs(self.localstatus) do
self.localstatus[k] = nil
end
self.scrollframe:SetPoint("BOTTOMRIGHT")
self.scrollbar:Hide()
self.scrollBarShown = nil
self.content.height, self.content.width = nil, nil
end,
["SetScroll"] = function(self, value)
local status = self.status or self.localstatus
local viewheight = self.scrollframe:GetHeight()
local height = self.content:GetHeight()
local offset
if viewheight > height then
offset = 0
else
offset = floor((height - viewheight) / 1000.0 * value)
end
self.content:ClearAllPoints()
self.content:SetPoint("TOPLEFT", 0, offset)
self.content:SetPoint("TOPRIGHT", 0, offset)
status.offset = offset
status.scrollvalue = value
end,
["MoveScroll"] = function(self, value)
local status = self.status or self.localstatus
local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight()
if self.scrollBarShown then
local diff = height - viewheight
local delta = 1
if value < 0 then
delta = -1
end
self.scrollbar:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
end
end,
["FixScroll"] = function(self)
if self.updateLock then return end
self.updateLock = true
local status = self.status or self.localstatus
local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight()
local offset = status.offset or 0
local curvalue = self.scrollbar:GetValue()
-- Give us a margin of error of 2 pixels to stop some conditions that i would blame on floating point inaccuracys
-- No-one is going to miss 2 pixels at the bottom of the frame, anyhow!
if viewheight < height + 2 then
if self.scrollBarShown then
self.scrollBarShown = nil
self.scrollbar:Hide()
self.scrollbar:SetValue(0)
self.scrollframe:SetPoint("BOTTOMRIGHT")
self:DoLayout()
end
else
if not self.scrollBarShown then
self.scrollBarShown = true
self.scrollbar:Show()
self.scrollframe:SetPoint("BOTTOMRIGHT", -20, 0)
self:DoLayout()
end
local value = (offset / (viewheight - height) * 1000)
if value > 1000 then value = 1000 end
self.scrollbar:SetValue(value)
self:SetScroll(value)
if value < 1000 then
self.content:ClearAllPoints()
self.content:SetPoint("TOPLEFT", 0, offset)
self.content:SetPoint("TOPRIGHT", 0, offset)
status.offset = offset
end
end
self.updateLock = nil
end,
["LayoutFinished"] = function(self, width, height)
self.content:SetHeight(height or 0 + 20)
self.scrollframe:SetScript("OnUpdate", FixScrollOnUpdate)
end,
["SetStatusTable"] = function(self, status)
assert(type(status) == "table")
self.status = status
if not status.scrollvalue then
status.scrollvalue = 0
end
end,
["OnWidthSet"] = function(self, width)
local content = self.content
content.width = width
end,
["OnHeightSet"] = function(self, height)
local content = self.content
content.height = height
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
local num = AceGUI:GetNextWidgetNum(Type)
local scrollframe = CreateFrame("ScrollFrame", nil, frame)
scrollframe:SetPoint("TOPLEFT")
scrollframe:SetPoint("BOTTOMRIGHT")
scrollframe:EnableMouseWheel(true)
scrollframe:SetScript("OnMouseWheel", ScrollFrame_OnMouseWheel)
scrollframe:SetScript("OnSizeChanged", ScrollFrame_OnSizeChanged)
local scrollbar = CreateFrame("Slider", ("AceConfigDialogScrollFrame%dScrollBar"):format(num), scrollframe, "UIPanelScrollBarTemplate")
scrollbar:SetPoint("TOPLEFT", scrollframe, "TOPRIGHT", 4, -16)
scrollbar:SetPoint("BOTTOMLEFT", scrollframe, "BOTTOMRIGHT", 4, 16)
scrollbar:SetMinMaxValues(0, 1000)
scrollbar:SetValueStep(1)
scrollbar:SetValue(0)
scrollbar:SetWidth(16)
scrollbar:Hide()
-- set the script as the last step, so it doesn't fire yet
scrollbar:SetScript("OnValueChanged", ScrollBar_OnScrollValueChanged)
local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND")
scrollbg:SetAllPoints(scrollbar)
scrollbg:SetTexture(0, 0, 0, 0.4)
--Container Support
local content = CreateFrame("Frame", nil, scrollframe)
content:SetPoint("TOPLEFT")
content:SetPoint("TOPRIGHT")
content:SetHeight(400)
scrollframe:SetScrollChild(content)
local widget = {
localstatus = { scrollvalue = 0 },
scrollframe = scrollframe,
scrollbar = scrollbar,
content = content,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
scrollframe.obj, scrollbar.obj = widget, widget
return AceGUI:RegisterAsContainer(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,69 @@
--[[-----------------------------------------------------------------------------
SimpleGroup Container
Simple container widget that just groups widgets.
-------------------------------------------------------------------------------]]
local Type, Version = "SimpleGroup", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local pairs = pairs
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetWidth(300)
self:SetHeight(100)
end,
-- ["OnRelease"] = nil,
["LayoutFinished"] = function(self, width, height)
if self.noAutoHeight then return end
self:SetHeight(height or 0)
end,
["OnWidthSet"] = function(self, width)
local content = self.content
content:SetWidth(width)
content.width = width
end,
["OnHeightSet"] = function(self, height)
local content = self.content
content:SetHeight(height)
content.height = height
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
--Container Support
local content = CreateFrame("Frame", nil, frame)
content:SetPoint("TOPLEFT")
content:SetPoint("BOTTOMRIGHT")
local widget = {
frame = frame,
content = content,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
return AceGUI:RegisterAsContainer(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,348 @@
--[[-----------------------------------------------------------------------------
TabGroup Container
Container that uses tabs on top to switch between groups.
-------------------------------------------------------------------------------]]
local Type, Version = "TabGroup", 30
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local pairs, ipairs, assert, type, wipe = pairs, ipairs, assert, type, wipe
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame, UIParent = CreateFrame, UIParent
local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: PanelTemplates_TabResize, PanelTemplates_SetDisabledTabState, PanelTemplates_SelectTab, PanelTemplates_DeselectTab
-- local upvalue storage used by BuildTabs
local widths = {}
local rowwidths = {}
local rowends = {}
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function UpdateTabLook(frame)
if frame.disabled then
PanelTemplates_SetDisabledTabState(frame)
elseif frame.selected then
PanelTemplates_SelectTab(frame)
else
PanelTemplates_DeselectTab(frame)
end
end
local function Tab_SetText(frame, text)
frame:_SetText(text)
local width = frame.obj.frame.width or frame.obj.frame:GetWidth() or 0
PanelTemplates_TabResize(frame, 0, nil, width)
end
local function Tab_SetSelected(frame, selected)
frame.selected = selected
UpdateTabLook(frame)
end
local function Tab_SetDisabled(frame, disabled)
frame.disabled = disabled
UpdateTabLook(frame)
end
local function BuildTabsOnUpdate(frame)
local self = frame.obj
self:BuildTabs()
frame:SetScript("OnUpdate", nil)
end
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Tab_OnClick(frame)
if not (frame.selected or frame.disabled) then
PlaySound("igCharacterInfoTab")
frame.obj:SelectTab(frame.value)
end
end
local function Tab_OnEnter(frame)
local self = frame.obj
self:Fire("OnTabEnter", self.tabs[frame.id].value, frame)
end
local function Tab_OnLeave(frame)
local self = frame.obj
self:Fire("OnTabLeave", self.tabs[frame.id].value, frame)
end
local function Tab_OnShow(frame)
_G[frame:GetName().."HighlightTexture"]:SetWidth(frame:GetTextWidth() + 30)
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetTitle()
end,
["OnRelease"] = function(self)
self.status = nil
for k in pairs(self.localstatus) do
self.localstatus[k] = nil
end
self.tablist = nil
for _, tab in pairs(self.tabs) do
tab:Hide()
end
end,
["CreateTab"] = function(self, id)
local tabname = ("AceGUITabGroup%dTab%d"):format(self.num, id)
local tab = CreateFrame("Button", tabname, self.border, "OptionsFrameTabButtonTemplate")
tab.obj = self
tab.id = id
tab.text = _G[tabname .. "Text"]
tab.text:ClearAllPoints()
tab.text:SetPoint("LEFT", 14, -3)
tab.text:SetPoint("RIGHT", -12, -3)
tab:SetScript("OnClick", Tab_OnClick)
tab:SetScript("OnEnter", Tab_OnEnter)
tab:SetScript("OnLeave", Tab_OnLeave)
tab:SetScript("OnShow", Tab_OnShow)
tab._SetText = tab.SetText
tab.SetText = Tab_SetText
tab.SetSelected = Tab_SetSelected
tab.SetDisabled = Tab_SetDisabled
return tab
end,
["SetTitle"] = function(self, text)
self.titletext:SetText(text or "")
if text and text ~= "" then
self.alignoffset = 25
else
self.alignoffset = 18
end
self:BuildTabs()
end,
["SetStatusTable"] = function(self, status)
assert(type(status) == "table")
self.status = status
end,
["SelectTab"] = function(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,
["SetTabs"] = function(self, tabs)
self.tablist = tabs
self:BuildTabs()
end,
["BuildTabs"] = function(self)
local hastitle = (self.titletext:GetText() and self.titletext:GetText() ~= "")
local status = self.status or self.localstatus
local tablist = self.tablist
local tabs = self.tabs
if not tablist then return end
local width = self.frame.width or self.frame:GetWidth() or 0
wipe(widths)
wipe(rowwidths)
wipe(rowends)
--Place Text into tabs and get thier initial width
for i, v in ipairs(tablist) do
local tab = tabs[i]
if not tab then
tab = self:CreateTab(i)
tabs[i] = tab
end
tab:Show()
tab:SetText(v.text)
tab:SetDisabled(v.disabled)
tab.value = v.value
widths[i] = tab:GetWidth() - 6 --tabs are anchored 10 pixels from the right side of the previous one to reduce spacing, but add a fixed 4px padding for the text
end
for i = (#tablist)+1, #tabs, 1 do
tabs[i]:Hide()
end
--First pass, find the minimum number of rows needed to hold all tabs and the initial tab layout
local numtabs = #tablist
local numrows = 1
local usedwidth = 0
for i = 1, #tablist do
--If this is not the first tab of a row and there isn't room for it
if usedwidth ~= 0 and (width - usedwidth - widths[i]) < 0 then
rowwidths[numrows] = usedwidth + 10 --first tab in each row takes up an extra 10px
rowends[numrows] = i - 1
numrows = numrows + 1
usedwidth = 0
end
usedwidth = usedwidth + widths[i]
end
rowwidths[numrows] = usedwidth + 10 --first tab in each row takes up an extra 10px
rowends[numrows] = #tablist
--Fix for single tabs being left on the last row, move a tab from the row above if applicable
if numrows > 1 then
--if the last row has only one tab
if rowends[numrows-1] == numtabs-1 then
--if there are more than 2 tabs in the 2nd last row
if (numrows == 2 and rowends[numrows-1] > 2) or (rowends[numrows] - rowends[numrows-1] > 2) then
--move 1 tab from the second last row to the last, if there is enough space
if (rowwidths[numrows] + widths[numtabs-1]) <= width then
rowends[numrows-1] = rowends[numrows-1] - 1
rowwidths[numrows] = rowwidths[numrows] + widths[numtabs-1]
rowwidths[numrows-1] = rowwidths[numrows-1] - widths[numtabs-1]
end
end
end
end
--anchor the rows as defined and resize tabs to fill thier row
local starttab = 1
for row, endtab in ipairs(rowends) do
local first = true
for tabno = starttab, endtab do
local tab = tabs[tabno]
tab:ClearAllPoints()
if first then
tab:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 0, -(hastitle and 14 or 7)-(row-1)*20 )
first = false
else
tab:SetPoint("LEFT", tabs[tabno-1], "RIGHT", -10, 0)
end
end
-- equal padding for each tab to fill the available width,
-- if the used space is above 75% already
local padding = 0
if not (numrows == 1 and rowwidths[1] < width*0.75) then
padding = (width - rowwidths[row]) / (endtab - starttab+1)
end
for i = starttab, endtab do
PanelTemplates_TabResize(tabs[i], padding + 4, nil, width)
end
starttab = endtab + 1
end
self.borderoffset = (hastitle and 17 or 10)+((numrows)*20)
self.border:SetPoint("TOPLEFT", 1, -self.borderoffset)
end,
["OnWidthSet"] = function(self, width)
local content = self.content
local contentwidth = width - 60
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
self:BuildTabs(self)
self.frame:SetScript("OnUpdate", BuildTabsOnUpdate)
end,
["OnHeightSet"] = function(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,
["LayoutFinished"] = function(self, width, height)
if self.noAutoHeight then return end
self:SetHeight((height or 0) + (self.borderoffset + 23))
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local PaneBackdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 3, right = 3, top = 5, bottom = 3 }
}
local function Constructor()
local num = AceGUI:GetNextWidgetNum(Type)
local frame = CreateFrame("Frame",nil,UIParent)
frame:SetHeight(100)
frame:SetWidth(100)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
local titletext = frame:CreateFontString(nil,"OVERLAY","GameFontNormal")
titletext:SetPoint("TOPLEFT", 14, 0)
titletext:SetPoint("TOPRIGHT", -14, 0)
titletext:SetJustifyH("LEFT")
titletext:SetHeight(18)
titletext:SetText("")
local border = CreateFrame("Frame", nil, frame)
border:SetPoint("TOPLEFT", 1, -27)
border:SetPoint("BOTTOMRIGHT", -1, 3)
border:SetBackdrop(PaneBackdrop)
border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
border:SetBackdropBorderColor(0.4, 0.4, 0.4)
local content = CreateFrame("Frame", nil, border)
content:SetPoint("TOPLEFT", 10, -7)
content:SetPoint("BOTTOMRIGHT", -10, 7)
local widget = {
num = num,
frame = frame,
localstatus = {},
alignoffset = 18,
titletext = titletext,
border = border,
borderoffset = 27,
tabs = {},
content = content,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
return AceGUI:RegisterAsContainer(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,670 @@
--[[-----------------------------------------------------------------------------
TreeGroup Container
Container that uses a tree control to switch between groups.
-------------------------------------------------------------------------------]]
local Type, Version = "TreeGroup", 30
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local next, pairs, ipairs, assert, type = next, pairs, ipairs, assert, type
local math_min, math_max, floor = math.min, math.max, floor
local select, tremove, unpack = select, table.remove, unpack
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GameTooltip, FONT_COLOR_CODE_CLOSE
-- Recycling functions
local new, del
do
local pool = setmetatable({},{__mode='k'})
function new()
local t = next(pool)
if t then
pool[t] = nil
return t
else
return {}
end
end
function del(t)
for k in pairs(t) do
t[k] = nil
end
pool[t] = true
end
end
local DEFAULT_TREE_WIDTH = 175
local DEFAULT_TREE_SIZABLE = true
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
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 UpdateButton(button, treeline, selected, canExpand, isExpanded)
local self = button.obj
local toggle = button.toggle
local frame = self.frame
local text = treeline.text or ""
local icon = treeline.icon
local iconCoords = treeline.iconCoords
local level = treeline.level
local value = treeline.value
local uniquevalue = treeline.uniquevalue
local disabled = treeline.disabled
button.treeline = treeline
button.value = value
button.uniquevalue = uniquevalue
if selected then
button:LockHighlight()
button.selected = true
else
button:UnlockHighlight()
button.selected = false
end
local normalTexture = button:GetNormalTexture()
local line = button.line
button.level = level
if ( level == 1 ) then
button:SetNormalFontObject("GameFontNormal")
button:SetHighlightFontObject("GameFontHighlight")
button.text:SetPoint("LEFT", (icon and 16 or 0) + 8, 2)
else
button:SetNormalFontObject("GameFontHighlightSmall")
button:SetHighlightFontObject("GameFontHighlightSmall")
button.text:SetPoint("LEFT", (icon and 16 or 0) + 8 * level, 2)
end
if disabled then
button:EnableMouse(false)
button.text:SetText("|cff808080"..text..FONT_COLOR_CODE_CLOSE)
else
button.text:SetText(text)
button:EnableMouse(true)
end
if icon then
button.icon:SetTexture(icon)
button.icon:SetPoint("LEFT", 8 * level, (level == 1) and 0 or 1)
else
button.icon:SetTexture(nil)
end
if iconCoords then
button.icon:SetTexCoord(unpack(iconCoords))
else
button.icon:SetTexCoord(0, 1, 0, 1)
end
if canExpand then
if not isExpanded then
toggle:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-UP")
toggle:SetPushedTexture("Interface\\Buttons\\UI-PlusButton-DOWN")
else
toggle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-UP")
toggle:SetPushedTexture("Interface\\Buttons\\UI-MinusButton-DOWN")
end
toggle:Show()
else
toggle:Hide()
end
end
local function ShouldDisplayLevel(tree)
local result = false
for k, v in ipairs(tree) do
if v.children == nil and v.visible ~= false then
result = true
elseif v.children then
result = result or ShouldDisplayLevel(v.children)
end
if result then return result end
end
return false
end
local function addLine(self, v, tree, level, parent)
local line = new()
line.value = v.value
line.text = v.text
line.icon = v.icon
line.iconCoords = v.iconCoords
line.disabled = v.disabled
line.tree = tree
line.level = level
line.parent = parent
line.visible = v.visible
line.uniquevalue = GetButtonUniqueValue(line)
if v.children then
line.hasChildren = true
else
line.hasChildren = nil
end
self.lines[#self.lines+1] = line
return line
end
--fire an update after one frame to catch the treeframes height
local function FirstFrameUpdate(frame)
local self = frame.obj
frame:SetScript("OnUpdate", nil)
self:RefreshTree()
end
local function BuildUniqueValue(...)
local n = select('#', ...)
if n == 1 then
return ...
else
return (...).."\001"..BuildUniqueValue(select(2,...))
end
end
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Expand_OnClick(frame)
local button = frame.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 Button_OnClick(frame)
local self = frame.obj
self:Fire("OnClick", frame.uniquevalue, frame.selected)
if not frame.selected then
self:SetSelected(frame.uniquevalue)
frame.selected = true
frame:LockHighlight()
self:RefreshTree()
end
AceGUI:ClearFocus()
end
local function Button_OnDoubleClick(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 Button_OnEnter(frame)
local self = frame.obj
self:Fire("OnButtonEnter", frame.uniquevalue, frame)
if self.enabletooltips then
GameTooltip:SetOwner(frame, "ANCHOR_NONE")
GameTooltip:SetPoint("LEFT",frame,"RIGHT")
GameTooltip:SetText(frame.text:GetText() or "", 1, .82, 0, 1)
GameTooltip:Show()
end
end
local function Button_OnLeave(frame)
local self = frame.obj
self:Fire("OnButtonLeave", frame.uniquevalue, frame)
if self.enabletooltips then
GameTooltip:Hide()
end
end
local function OnScrollValueChanged(frame, value)
if frame.obj.noupdate then return end
local self = frame.obj
local status = self.status or self.localstatus
status.scrollvalue = value
self:RefreshTree()
AceGUI:ClearFocus()
end
local function Tree_OnSizeChanged(frame)
frame.obj:RefreshTree()
end
local function Tree_OnMouseWheel(frame, delta)
local self = frame.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 Dragger_OnLeave(frame)
frame:SetBackdropColor(1, 1, 1, 0)
end
local function Dragger_OnEnter(frame)
frame:SetBackdropColor(1, 1, 1, 0.8)
end
local function Dragger_OnMouseDown(frame)
local treeframe = frame:GetParent()
treeframe:StartSizing("RIGHT")
end
local function Dragger_OnMouseUp(frame)
local treeframe = frame:GetParent()
local self = treeframe.obj
local frame = treeframe:GetParent()
treeframe:StopMovingOrSizing()
--treeframe:SetScript("OnUpdate", nil)
treeframe:SetUserPlaced(false)
--Without this :GetHeight will get stuck on the current height, causing the tree contents to not resize
treeframe:SetHeight(0)
treeframe:SetPoint("TOPLEFT", frame, "TOPLEFT",0,0)
treeframe:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT",0,0)
local status = self.status or self.localstatus
status.treewidth = treeframe:GetWidth()
treeframe.obj:Fire("OnTreeResize",treeframe:GetWidth())
-- recalculate the content width
treeframe.obj:OnWidthSet(status.fullwidth)
-- update the layout of the content
treeframe.obj:DoLayout()
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetTreeWidth(DEFAULT_TREE_WIDTH, DEFAULT_TREE_SIZABLE)
self:EnableButtonTooltips(true)
end,
["OnRelease"] = function(self)
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,
["EnableButtonTooltips"] = function(self, enable)
self.enabletooltips = enable
end,
["CreateButton"] = function(self)
local num = AceGUI:GetNextWidgetNum("TreeGroupButton")
local button = CreateFrame("Button", ("AceGUI30TreeButton%d"):format(num), self.treeframe, "OptionsListButtonTemplate")
button.obj = self
local icon = button:CreateTexture(nil, "OVERLAY")
icon:SetWidth(14)
icon:SetHeight(14)
button.icon = icon
button:SetScript("OnClick",Button_OnClick)
button:SetScript("OnDoubleClick", Button_OnDoubleClick)
button:SetScript("OnEnter",Button_OnEnter)
button:SetScript("OnLeave",Button_OnLeave)
button.toggle.button = button
button.toggle:SetScript("OnClick",Expand_OnClick)
return button
end,
["SetStatusTable"] = function(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
["SetTree"] = function(self, tree, filter)
self.filter = filter
if tree then
assert(type(tree) == "table")
end
self.tree = tree
self:RefreshTree()
end,
["BuildLevel"] = function(self, tree, level, parent)
local groups = (self.status or self.localstatus).groups
local hasChildren = self.hasChildren
for i, v in ipairs(tree) do
if v.children then
if not self.filter or ShouldDisplayLevel(v.children) then
local line = addLine(self, v, tree, level, parent)
if groups[line.uniquevalue] then
self:BuildLevel(v.children, level+1, line)
end
end
elseif v.visible ~= false or not self.filter then
addLine(self, v, tree, level, parent)
end
end
end,
["RefreshTree"] = function(self)
local buttons = self.buttons
local lines = self.lines
for i, v in ipairs(buttons) do
v:Hide()
end
while lines[1] do
local t = tremove(lines)
for k in pairs(t) do
t[k] = nil
end
del(t)
end
if not self.tree then return end
--Build the list of visible entries from the tree and status tables
local status = self.status or self.localstatus
local groupstatus = status.groups
local tree = self.tree
local treeframe = self.treeframe
self:BuildLevel(tree, 1)
local numlines = #lines
local maxlines = (floor(((self.treeframe:GetHeight()or 0) - 20 ) / 18))
local first, last
if numlines <= maxlines then
--the whole tree fits in the frame
status.scrollvalue = 0
self:ShowScroll(false)
first, last = 1, numlines
else
self:ShowScroll(true)
--scrolling will be needed
self.noupdate = true
self.scrollbar:SetMinMaxValues(0, numlines - maxlines)
--check if we are scrolled down too far
if numlines - status.scrollvalue < maxlines then
status.scrollvalue = numlines - maxlines
self.scrollbar:SetValue(status.scrollvalue)
end
self.noupdate = nil
first, last = status.scrollvalue+1, status.scrollvalue + maxlines
end
local buttonnum = 1
for i = first, last do
local line = lines[i]
local button = buttons[buttonnum]
if not button then
button = self:CreateButton()
buttons[buttonnum] = button
button:SetParent(treeframe)
button:SetFrameLevel(treeframe:GetFrameLevel()+1)
button:ClearAllPoints()
if i == 1 then
if self.showscroll then
button:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",-22,-10)
button:SetPoint("TOPLEFT", self.treeframe, "TOPLEFT", 0, -10)
else
button:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",0,-10)
button:SetPoint("TOPLEFT", self.treeframe, "TOPLEFT", 0, -10)
end
else
button:SetPoint("TOPRIGHT", buttons[buttonnum-1], "BOTTOMRIGHT",0,0)
button:SetPoint("TOPLEFT", buttons[buttonnum-1], "BOTTOMLEFT",0,0)
end
end
UpdateButton(button, line, status.selected == line.uniquevalue, line.hasChildren, groupstatus[line.uniquevalue] )
button:Show()
buttonnum = buttonnum + 1
end
end,
["SetSelected"] = function(self, value)
local status = self.status or self.localstatus
if status.selected ~= value then
status.selected = value
self:Fire("OnGroupSelected", value)
end
end,
["Select"] = function(self, uniquevalue, ...)
self.filter = false
local status = self.status or self.localstatus
local groups = status.groups
for i = 1, select('#', ...) do
groups[BuildUniqueValue(select(i, ...))] = true
end
status.selected = uniquevalue
self:RefreshTree()
self:Fire("OnGroupSelected", uniquevalue)
end,
["SelectByPath"] = function(self, ...)
self:Select(BuildUniqueValue(...), ...)
end,
["SelectByValue"] = function(self, uniquevalue)
self:Select(uniquevalue, ("\001"):split(uniquevalue))
end,
["ShowScroll"] = function(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,
["OnWidthSet"] = function(self, width)
local content = self.content
local treeframe = self.treeframe
local status = self.status or self.localstatus
status.fullwidth = width
local contentwidth = width - status.treewidth - 20
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
local maxtreewidth = math_min(400, width - 50)
if maxtreewidth > 100 and status.treewidth > maxtreewidth then
self:SetTreeWidth(maxtreewidth, status.treesizable)
end
treeframe:SetMaxResize(maxtreewidth, 1600)
end,
["OnHeightSet"] = function(self, height)
local content = self.content
local contentheight = height - 20
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end,
["SetTreeWidth"] = function(self, treewidth, resizable)
if not resizable then
if type(treewidth) == 'number' then
resizable = false
elseif type(treewidth) == 'boolean' then
resizable = treewidth
treewidth = DEFAULT_TREE_WIDTH
else
resizable = false
treewidth = DEFAULT_TREE_WIDTH
end
end
self.treeframe:SetWidth(treewidth)
self.dragger:EnableMouse(resizable)
local status = self.status or self.localstatus
status.treewidth = treewidth
status.treesizable = resizable
-- recalculate the content width
if status.fullwidth then
self:OnWidthSet(status.fullwidth)
end
end,
["LayoutFinished"] = function(self, width, height)
if self.noAutoHeight then return end
self:SetHeight((height or 0) + 20)
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
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 Constructor()
local num = AceGUI:GetNextWidgetNum(Type)
local frame = CreateFrame("Frame", nil, UIParent)
local treeframe = CreateFrame("Frame", nil, frame)
treeframe:SetPoint("TOPLEFT")
treeframe:SetPoint("BOTTOMLEFT")
treeframe:SetWidth(DEFAULT_TREE_WIDTH)
treeframe:EnableMouseWheel(true)
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)
treeframe:SetScript("OnUpdate", FirstFrameUpdate)
treeframe:SetScript("OnSizeChanged", Tree_OnSizeChanged)
treeframe:SetScript("OnMouseWheel", Tree_OnMouseWheel)
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("OnEnter", Dragger_OnEnter)
dragger:SetScript("OnLeave", Dragger_OnLeave)
dragger:SetScript("OnMouseDown", Dragger_OnMouseDown)
dragger:SetScript("OnMouseUp", Dragger_OnMouseUp)
local scrollbar = CreateFrame("Slider", ("AceConfigDialogTreeGroup%dScrollBar"):format(num), treeframe, "UIPanelScrollBarTemplate")
scrollbar:SetScript("OnValueChanged", nil)
scrollbar:SetPoint("TOPRIGHT", -10, -26)
scrollbar:SetPoint("BOTTOMRIGHT", -10, 26)
scrollbar:SetMinMaxValues(0,0)
scrollbar:SetValueStep(1)
scrollbar:SetValue(0)
scrollbar:SetWidth(16)
scrollbar:SetScript("OnValueChanged", OnScrollValueChanged)
local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND")
scrollbg:SetAllPoints(scrollbar)
scrollbg:SetTexture(0,0,0,0.4)
local border = CreateFrame("Frame",nil,frame)
border:SetPoint("TOPLEFT", treeframe, "TOPRIGHT")
border:SetPoint("BOTTOMRIGHT")
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)
content:SetPoint("TOPLEFT", 10, -10)
content:SetPoint("BOTTOMRIGHT", -10, 10)
local widget = {
frame = frame,
lines = {},
levels = {},
buttons = {},
hasChildren = {},
localstatus = { groups = {}, scrollvalue = 0 },
filter = false,
treeframe = treeframe,
dragger = dragger,
scrollbar = scrollbar,
border = border,
content = content,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
treeframe.obj, dragger.obj, scrollbar.obj = widget, widget, widget
return AceGUI:RegisterAsContainer(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,331 @@
local AceGUI = LibStub("AceGUI-3.0")
-- Lua APIs
local pairs, assert, type = pairs, assert, type
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame, UIParent = CreateFrame, UIParent
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GameFontNormal
----------------
-- Main Frame --
----------------
--[[
Events :
OnClose
]]
do
local Type = "Window"
local Version = 4
local function frameOnClose(this)
this.obj:Fire("OnClose")
end
local function closeOnClick(this)
PlaySound("gsTitleOptionExit")
this.obj:Hide()
end
local function frameOnMouseDown(this)
AceGUI:ClearFocus()
end
local function titleOnMouseDown(this)
this:GetParent():StartMoving()
AceGUI:ClearFocus()
end
local function frameOnMouseUp(this)
local frame = this:GetParent()
frame:StopMovingOrSizing()
local self = frame.obj
local status = self.status or self.localstatus
status.width = frame:GetWidth()
status.height = frame:GetHeight()
status.top = frame:GetTop()
status.left = frame:GetLeft()
end
local function sizerseOnMouseDown(this)
this:GetParent():StartSizing("BOTTOMRIGHT")
AceGUI:ClearFocus()
end
local function sizersOnMouseDown(this)
this:GetParent():StartSizing("BOTTOM")
AceGUI:ClearFocus()
end
local function sizereOnMouseDown(this)
this:GetParent():StartSizing("RIGHT")
AceGUI:ClearFocus()
end
local function sizerOnMouseUp(this)
this:GetParent():StopMovingOrSizing()
end
local function SetTitle(self,title)
self.titletext:SetText(title)
end
local function SetStatusText(self,text)
-- self.statustext:SetText(text)
end
local function Hide(self)
self.frame:Hide()
end
local function Show(self)
self.frame:Show()
end
local function OnAcquire(self)
self.frame:SetParent(UIParent)
self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
self:ApplyStatus()
self:EnableResize(true)
self:Show()
end
local function OnRelease(self)
self.status = nil
for k in pairs(self.localstatus) do
self.localstatus[k] = nil
end
end
-- called to set an external table to store status in
local function SetStatusTable(self, status)
assert(type(status) == "table")
self.status = status
self:ApplyStatus()
end
local function ApplyStatus(self)
local status = self.status or self.localstatus
local frame = self.frame
self:SetWidth(status.width or 700)
self:SetHeight(status.height or 500)
if status.top and status.left then
frame:SetPoint("TOP",UIParent,"BOTTOM",0,status.top)
frame:SetPoint("LEFT",UIParent,"LEFT",status.left,0)
else
frame:SetPoint("CENTER",UIParent,"CENTER")
end
end
local function OnWidthSet(self, width)
local content = self.content
local contentwidth = width - 34
if contentwidth < 0 then
contentwidth = 0
end
content:SetWidth(contentwidth)
content.width = contentwidth
end
local function OnHeightSet(self, height)
local content = self.content
local contentheight = height - 57
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end
local function EnableResize(self, state)
local func = state and "Show" or "Hide"
self.sizer_se[func](self.sizer_se)
self.sizer_s[func](self.sizer_s)
self.sizer_e[func](self.sizer_e)
end
local function Constructor()
local frame = CreateFrame("Frame",nil,UIParent)
local self = {}
self.type = "Window"
self.Hide = Hide
self.Show = Show
self.SetTitle = SetTitle
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
self.SetStatusText = SetStatusText
self.SetStatusTable = SetStatusTable
self.ApplyStatus = ApplyStatus
self.OnWidthSet = OnWidthSet
self.OnHeightSet = OnHeightSet
self.EnableResize = EnableResize
self.localstatus = {}
self.frame = frame
frame.obj = self
frame:SetWidth(700)
frame:SetHeight(500)
frame:SetPoint("CENTER",UIParent,"CENTER",0,0)
frame:EnableMouse()
frame:SetMovable(true)
frame:SetResizable(true)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
frame:SetScript("OnMouseDown", frameOnMouseDown)
frame:SetScript("OnHide",frameOnClose)
frame:SetMinResize(240,240)
frame:SetToplevel(true)
local titlebg = frame:CreateTexture(nil, "BACKGROUND")
titlebg:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Title-Background]])
titlebg:SetPoint("TOPLEFT", 9, -6)
titlebg:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", -28, -24)
local dialogbg = frame:CreateTexture(nil, "BACKGROUND")
dialogbg:SetTexture([[Interface\Tooltips\UI-Tooltip-Background]])
dialogbg:SetPoint("TOPLEFT", 8, -24)
dialogbg:SetPoint("BOTTOMRIGHT", -6, 8)
dialogbg:SetVertexColor(0, 0, 0, .75)
local topleft = frame:CreateTexture(nil, "BORDER")
topleft:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
topleft:SetWidth(64)
topleft:SetHeight(64)
topleft:SetPoint("TOPLEFT")
topleft:SetTexCoord(0.501953125, 0.625, 0, 1)
local topright = frame:CreateTexture(nil, "BORDER")
topright:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
topright:SetWidth(64)
topright:SetHeight(64)
topright:SetPoint("TOPRIGHT")
topright:SetTexCoord(0.625, 0.75, 0, 1)
local top = frame:CreateTexture(nil, "BORDER")
top:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
top:SetHeight(64)
top:SetPoint("TOPLEFT", topleft, "TOPRIGHT")
top:SetPoint("TOPRIGHT", topright, "TOPLEFT")
top:SetTexCoord(0.25, 0.369140625, 0, 1)
local bottomleft = frame:CreateTexture(nil, "BORDER")
bottomleft:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
bottomleft:SetWidth(64)
bottomleft:SetHeight(64)
bottomleft:SetPoint("BOTTOMLEFT")
bottomleft:SetTexCoord(0.751953125, 0.875, 0, 1)
local bottomright = frame:CreateTexture(nil, "BORDER")
bottomright:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
bottomright:SetWidth(64)
bottomright:SetHeight(64)
bottomright:SetPoint("BOTTOMRIGHT")
bottomright:SetTexCoord(0.875, 1, 0, 1)
local bottom = frame:CreateTexture(nil, "BORDER")
bottom:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
bottom:SetHeight(64)
bottom:SetPoint("BOTTOMLEFT", bottomleft, "BOTTOMRIGHT")
bottom:SetPoint("BOTTOMRIGHT", bottomright, "BOTTOMLEFT")
bottom:SetTexCoord(0.376953125, 0.498046875, 0, 1)
local left = frame:CreateTexture(nil, "BORDER")
left:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
left:SetWidth(64)
left:SetPoint("TOPLEFT", topleft, "BOTTOMLEFT")
left:SetPoint("BOTTOMLEFT", bottomleft, "TOPLEFT")
left:SetTexCoord(0.001953125, 0.125, 0, 1)
local right = frame:CreateTexture(nil, "BORDER")
right:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
right:SetWidth(64)
right:SetPoint("TOPRIGHT", topright, "BOTTOMRIGHT")
right:SetPoint("BOTTOMRIGHT", bottomright, "TOPRIGHT")
right:SetTexCoord(0.1171875, 0.2421875, 0, 1)
local close = CreateFrame("Button", nil, frame, "UIPanelCloseButton")
close:SetPoint("TOPRIGHT", 2, 1)
close:SetScript("OnClick", closeOnClick)
self.closebutton = close
close.obj = self
local titletext = frame:CreateFontString(nil, "ARTWORK")
titletext:SetFontObject(GameFontNormal)
titletext:SetPoint("TOPLEFT", 12, -8)
titletext:SetPoint("TOPRIGHT", -32, -8)
self.titletext = titletext
local title = CreateFrame("Button", nil, frame)
title:SetPoint("TOPLEFT", titlebg)
title:SetPoint("BOTTOMRIGHT", titlebg)
title:EnableMouse()
title:SetScript("OnMouseDown",titleOnMouseDown)
title:SetScript("OnMouseUp", frameOnMouseUp)
self.title = title
local sizer_se = CreateFrame("Frame",nil,frame)
sizer_se:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0)
sizer_se:SetWidth(25)
sizer_se:SetHeight(25)
sizer_se:EnableMouse()
sizer_se:SetScript("OnMouseDown",sizerseOnMouseDown)
sizer_se:SetScript("OnMouseUp", sizerOnMouseUp)
self.sizer_se = sizer_se
local line1 = sizer_se:CreateTexture(nil, "BACKGROUND")
self.line1 = line1
line1:SetWidth(14)
line1:SetHeight(14)
line1:SetPoint("BOTTOMRIGHT", -8, 8)
line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
local x = 0.1 * 14/17
line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
local line2 = sizer_se:CreateTexture(nil, "BACKGROUND")
self.line2 = line2
line2:SetWidth(8)
line2:SetHeight(8)
line2:SetPoint("BOTTOMRIGHT", -8, 8)
line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
local x = 0.1 * 8/17
line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
local sizer_s = CreateFrame("Frame",nil,frame)
sizer_s:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-25,0)
sizer_s:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,0)
sizer_s:SetHeight(25)
sizer_s:EnableMouse()
sizer_s:SetScript("OnMouseDown",sizersOnMouseDown)
sizer_s:SetScript("OnMouseUp", sizerOnMouseUp)
self.sizer_s = sizer_s
local sizer_e = CreateFrame("Frame",nil,frame)
sizer_e:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,25)
sizer_e:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
sizer_e:SetWidth(25)
sizer_e:EnableMouse()
sizer_e:SetScript("OnMouseDown",sizereOnMouseDown)
sizer_e:SetScript("OnMouseUp", sizerOnMouseUp)
self.sizer_e = sizer_e
--Container Support
local content = CreateFrame("Frame",nil,frame)
self.content = content
content.obj = self
content:SetPoint("TOPLEFT",frame,"TOPLEFT",12,-32)
content:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-12,13)
AceGUI:RegisterAsContainer(self)
return self
end
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end

View File

@@ -0,0 +1,92 @@
--[[-----------------------------------------------------------------------------
Button Widget
Graphical Button.
-------------------------------------------------------------------------------]]
local Type, Version = "Button", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local pairs = pairs
-- WoW APIs
local _G = _G
local PlaySound, CreateFrame, UIParent = PlaySound, CreateFrame, UIParent
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Button_OnClick(frame, ...)
PlaySound("igMainMenuOption")
frame.obj:Fire("OnClick", ...)
AceGUI:ClearFocus()
end
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
-- restore default values
self:SetHeight(24)
self:SetWidth(200)
self:SetDisabled(false)
self:SetText()
end,
-- ["OnRelease"] = nil,
["SetText"] = function(self, text)
self.text:SetText(text)
end,
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if disabled then
self.frame:Disable()
else
self.frame:Enable()
end
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local name = "AceGUI30Button" .. AceGUI:GetNextWidgetNum(Type)
local frame = CreateFrame("Button", name, UIParent, "UIPanelButtonTemplate2")
frame:Hide()
frame:EnableMouse(true)
frame:SetScript("OnClick", Button_OnClick)
frame:SetScript("OnEnter", Control_OnEnter)
frame:SetScript("OnLeave", Control_OnLeave)
local text = frame:GetFontString()
text:ClearAllPoints()
text:SetPoint("TOPLEFT", 15, -1)
text:SetPoint("BOTTOMRIGHT", -15, 1)
text:SetJustifyV("MIDDLE")
local widget = {
text = text,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
return AceGUI:RegisterAsWidget(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,289 @@
--[[-----------------------------------------------------------------------------
Checkbox Widget
-------------------------------------------------------------------------------]]
local Type, Version = "CheckBox", 21
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local select, pairs = select, pairs
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame, UIParent = CreateFrame, UIParent
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: SetDesaturation, GameFontHighlight
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function AlignImage(self)
local img = self.image:GetTexture()
self.text:ClearAllPoints()
if not img then
self.text:SetPoint("LEFT", self.checkbg, "RIGHT")
self.text:SetPoint("RIGHT")
else
self.text:SetPoint("LEFT", self.image,"RIGHT", 1, 0)
self.text:SetPoint("RIGHT")
end
end
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
local function CheckBox_OnMouseDown(frame)
local self = frame.obj
if not self.disabled then
if self.image:GetTexture() then
self.text:SetPoint("LEFT", self.image,"RIGHT", 2, -1)
else
self.text:SetPoint("LEFT", self.checkbg, "RIGHT", 1, -1)
end
end
AceGUI:ClearFocus()
end
local function CheckBox_OnMouseUp(frame)
local self = frame.obj
if not self.disabled then
self:ToggleChecked()
if self.checked then
PlaySound("igMainMenuOptionCheckBoxOn")
else -- for both nil and false (tristate)
PlaySound("igMainMenuOptionCheckBoxOff")
end
self:Fire("OnValueChanged", self.checked)
AlignImage(self)
end
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetType()
self:SetValue(false)
self:SetTriState(nil)
-- height is calculated from the width and required space for the description
self:SetWidth(200)
self:SetImage()
self:SetDisabled(nil)
self:SetDescription(nil)
end,
-- ["OnRelease"] = nil,
["OnWidthSet"] = function(self, width)
if self.desc then
self.desc:SetWidth(width - 30)
if self.desc:GetText() and self.desc:GetText() ~= "" then
self:SetHeight(28 + self.desc:GetHeight())
end
end
end,
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if disabled then
self.frame:Disable()
self.text:SetTextColor(0.5, 0.5, 0.5)
SetDesaturation(self.check, true)
else
self.frame:Enable()
self.text:SetTextColor(1, 1, 1)
if self.tristate and self.checked == nil then
SetDesaturation(self.check, true)
else
SetDesaturation(self.check, false)
end
end
end,
["SetValue"] = function(self,value)
local check = self.check
self.checked = value
if value then
SetDesaturation(self.check, false)
self.check:Show()
else
--Nil is the unknown tristate value
if self.tristate and value == nil then
SetDesaturation(self.check, true)
self.check:Show()
else
SetDesaturation(self.check, false)
self.check:Hide()
end
end
self:SetDisabled(self.disabled)
end,
["GetValue"] = function(self)
return self.checked
end,
["SetTriState"] = function(self, enabled)
self.tristate = enabled
self:SetValue(self:GetValue())
end,
["SetType"] = function(self, type)
local checkbg = self.checkbg
local check = self.check
local highlight = self.highlight
local size
if type == "radio" then
size = 16
checkbg:SetTexture("Interface\\Buttons\\UI-RadioButton")
checkbg:SetTexCoord(0, 0.25, 0, 1)
check:SetTexture("Interface\\Buttons\\UI-RadioButton")
check:SetTexCoord(0.25, 0.5, 0, 1)
check:SetBlendMode("ADD")
highlight:SetTexture("Interface\\Buttons\\UI-RadioButton")
highlight:SetTexCoord(0.5, 0.75, 0, 1)
else
size = 24
checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
checkbg:SetTexCoord(0, 1, 0, 1)
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
check:SetTexCoord(0, 1, 0, 1)
check:SetBlendMode("BLEND")
highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
highlight:SetTexCoord(0, 1, 0, 1)
end
checkbg:SetHeight(size)
checkbg:SetWidth(size)
end,
["ToggleChecked"] = function(self)
local value = self:GetValue()
if self.tristate then
--cycle in true, nil, false order
if value then
self:SetValue(nil)
elseif value == nil then
self:SetValue(false)
else
self:SetValue(true)
end
else
self:SetValue(not self:GetValue())
end
end,
["SetLabel"] = function(self, label)
self.text:SetText(label)
end,
["SetDescription"] = function(self, desc)
if desc then
if not self.desc then
local desc = self.frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
desc:ClearAllPoints()
desc:SetPoint("TOPLEFT", self.checkbg, "TOPRIGHT", 5, -21)
desc:SetWidth(self.frame.width - 30)
desc:SetJustifyH("LEFT")
desc:SetJustifyV("TOP")
self.desc = desc
end
self.desc:Show()
--self.text:SetFontObject(GameFontNormal)
self.desc:SetText(desc)
self:SetHeight(28 + self.desc:GetHeight())
else
if self.desc then
self.desc:SetText("")
self.desc:Hide()
end
--self.text:SetFontObject(GameFontHighlight)
self:SetHeight(24)
end
end,
["SetImage"] = function(self, path, ...)
local image = self.image
image:SetTexture(path)
if image:GetTexture() then
local n = select("#", ...)
if n == 4 or n == 8 then
image:SetTexCoord(...)
else
image:SetTexCoord(0, 1, 0, 1)
end
end
AlignImage(self)
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Button", nil, UIParent)
frame:Hide()
frame:EnableMouse(true)
frame:SetScript("OnEnter", Control_OnEnter)
frame:SetScript("OnLeave", Control_OnLeave)
frame:SetScript("OnMouseDown", CheckBox_OnMouseDown)
frame:SetScript("OnMouseUp", CheckBox_OnMouseUp)
local checkbg = frame:CreateTexture(nil, "ARTWORK")
checkbg:SetWidth(24)
checkbg:SetHeight(24)
checkbg:SetPoint("TOPLEFT")
checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
local check = frame:CreateTexture(nil, "OVERLAY")
check:SetAllPoints(checkbg)
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
local text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
text:SetJustifyH("LEFT")
text:SetHeight(18)
text:SetPoint("LEFT", checkbg, "RIGHT")
text:SetPoint("RIGHT")
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
highlight:SetBlendMode("ADD")
highlight:SetAllPoints(checkbg)
local image = frame:CreateTexture(nil, "OVERLAY")
image:SetHeight(16)
image:SetWidth(16)
image:SetPoint("LEFT", checkbg, "RIGHT", 1, 0)
local widget = {
checkbg = checkbg,
check = check,
text = text,
highlight = highlight,
image = image,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
return AceGUI:RegisterAsWidget(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,186 @@
--[[-----------------------------------------------------------------------------
ColorPicker Widget
-------------------------------------------------------------------------------]]
local Type, Version = "ColorPicker", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local pairs = pairs
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: ShowUIPanel, HideUIPanel, ColorPickerFrame, OpacitySliderFrame
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function ColorCallback(self, r, g, b, a, isAlpha)
if not self.HasAlpha then
a = 1
end
self:SetColor(r, g, b, a)
if ColorPickerFrame:IsVisible() then
--colorpicker is still open
self:Fire("OnValueChanged", r, g, b, a)
else
--colorpicker is closed, color callback is first, ignore it,
--alpha callback is the final call after it closes so confirm now
if isAlpha then
self:Fire("OnValueConfirmed", r, g, b, a)
end
end
end
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
local function ColorSwatch_OnClick(frame)
HideUIPanel(ColorPickerFrame)
local self = frame.obj
if not self.disabled then
ColorPickerFrame:SetFrameStrata("FULLSCREEN_DIALOG")
ColorPickerFrame.func = function()
local r, g, b = ColorPickerFrame:GetColorRGB()
local a = 1 - OpacitySliderFrame:GetValue()
ColorCallback(self, r, g, b, a)
end
ColorPickerFrame.hasOpacity = self.HasAlpha
ColorPickerFrame.opacityFunc = function()
local r, g, b = ColorPickerFrame:GetColorRGB()
local a = 1 - OpacitySliderFrame:GetValue()
ColorCallback(self, r, g, b, a, true)
end
local r, g, b, a = self.r, self.g, self.b, self.a
if self.HasAlpha then
ColorPickerFrame.opacity = 1 - (a or 0)
end
ColorPickerFrame:SetColorRGB(r, g, b)
ColorPickerFrame.cancelFunc = function()
ColorCallback(self, r, g, b, a, true)
end
ShowUIPanel(ColorPickerFrame)
end
AceGUI:ClearFocus()
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetHeight(24)
self:SetWidth(200)
self:SetHasAlpha(false)
self:SetColor(0, 0, 0, 1)
self:SetDisabled(nil)
self:SetLabel(nil)
end,
-- ["OnRelease"] = nil,
["SetLabel"] = function(self, text)
self.text:SetText(text)
end,
["SetColor"] = function(self, r, g, b, a)
self.r = r
self.g = g
self.b = b
self.a = a or 1
self.colorSwatch:SetVertexColor(r, g, b, a)
end,
["SetHasAlpha"] = function(self, HasAlpha)
self.HasAlpha = HasAlpha
end,
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if self.disabled then
self.frame:Disable()
self.text:SetTextColor(0.5, 0.5, 0.5)
else
self.frame:Enable()
self.text:SetTextColor(1, 1, 1)
end
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Button", nil, UIParent)
frame:Hide()
frame:EnableMouse(true)
frame:SetScript("OnEnter", Control_OnEnter)
frame:SetScript("OnLeave", Control_OnLeave)
frame:SetScript("OnClick", ColorSwatch_OnClick)
local colorSwatch = frame:CreateTexture(nil, "OVERLAY")
colorSwatch:SetWidth(19)
colorSwatch:SetHeight(19)
colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch")
colorSwatch:SetPoint("LEFT")
local texture = frame:CreateTexture(nil, "BACKGROUND")
texture:SetWidth(16)
texture:SetHeight(16)
texture:SetTexture(1, 1, 1)
texture:SetPoint("CENTER", colorSwatch)
texture:Show()
local checkers = frame:CreateTexture(nil, "BACKGROUND")
checkers:SetWidth(14)
checkers:SetHeight(14)
checkers:SetTexture("Tileset\\Generic\\Checkers")
checkers:SetTexCoord(.25, 0, 0.5, .25)
checkers:SetDesaturated(true)
checkers:SetVertexColor(1, 1, 1, 0.75)
checkers:SetPoint("CENTER", colorSwatch)
checkers:Show()
local text = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight")
text:SetHeight(24)
text:SetJustifyH("LEFT")
text:SetTextColor(1, 1, 1)
text:SetPoint("LEFT", colorSwatch, "RIGHT", 2, 0)
text:SetPoint("RIGHT")
--local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
--highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
--highlight:SetBlendMode("ADD")
--highlight:SetAllPoints(frame)
local widget = {
colorSwatch = colorSwatch,
text = text,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
return AceGUI:RegisterAsWidget(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,465 @@
--[[ $Id: AceGUIWidget-DropDown-Items.lua 916 2010-03-15 12:24:36Z nevcairiel $ ]]--
local AceGUI = LibStub("AceGUI-3.0")
-- Lua APIs
local select, assert = select, assert
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame = CreateFrame
local function fixlevels(parent,...)
local i = 1
local child = select(i, ...)
while child do
child:SetFrameLevel(parent:GetFrameLevel()+1)
fixlevels(child, child:GetChildren())
i = i + 1
child = select(i, ...)
end
end
local function fixstrata(strata, parent, ...)
local i = 1
local child = select(i, ...)
parent:SetFrameStrata(strata)
while child do
fixstrata(strata, child, child:GetChildren())
i = i + 1
child = select(i, ...)
end
end
-- ItemBase is the base "class" for all dropdown items.
-- Each item has to use ItemBase.Create(widgetType) to
-- create an initial 'self' value.
-- ItemBase will add common functions and ui event handlers.
-- Be sure to keep basic usage when you override functions.
local ItemBase = {
-- NOTE: The ItemBase version is added to each item's version number
-- to ensure proper updates on ItemBase changes.
-- Use at least 1000er steps.
version = 1000,
counter = 0,
}
function ItemBase.Frame_OnEnter(this)
local self = this.obj
if self.useHighlight then
self.highlight:Show()
end
self:Fire("OnEnter")
if self.specialOnEnter then
self.specialOnEnter(self)
end
end
function ItemBase.Frame_OnLeave(this)
local self = this.obj
self.highlight:Hide()
self:Fire("OnLeave")
if self.specialOnLeave then
self.specialOnLeave(self)
end
end
-- exported, AceGUI callback
function ItemBase.OnAcquire(self)
self.frame:SetToplevel(true)
self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
end
-- exported, AceGUI callback
function ItemBase.OnRelease(self)
self:SetDisabled(false)
self.pullout = nil
self.frame:SetParent(nil)
self.frame:ClearAllPoints()
self.frame:Hide()
end
-- exported
-- NOTE: this is called by a Dropdown-Pullout.
-- Do not call this method directly
function ItemBase.SetPullout(self, pullout)
self.pullout = pullout
self.frame:SetParent(nil)
self.frame:SetParent(pullout.itemFrame)
self.parent = pullout.itemFrame
fixlevels(pullout.itemFrame, pullout.itemFrame:GetChildren())
end
-- exported
function ItemBase.SetText(self, text)
self.text:SetText(text or "")
end
-- exported
function ItemBase.GetText(self)
return self.text:GetText()
end
-- exported
function ItemBase.SetPoint(self, ...)
self.frame:SetPoint(...)
end
-- exported
function ItemBase.Show(self)
self.frame:Show()
end
-- exported
function ItemBase.Hide(self)
self.frame:Hide()
end
-- exported
function ItemBase.SetDisabled(self, disabled)
self.disabled = disabled
if disabled then
self.useHighlight = false
self.text:SetTextColor(.5, .5, .5)
else
self.useHighlight = true
self.text:SetTextColor(1, 1, 1)
end
end
-- exported
-- NOTE: this is called by a Dropdown-Pullout.
-- Do not call this method directly
function ItemBase.SetOnLeave(self, func)
self.specialOnLeave = func
end
-- exported
-- NOTE: this is called by a Dropdown-Pullout.
-- Do not call this method directly
function ItemBase.SetOnEnter(self, func)
self.specialOnEnter = func
end
function ItemBase.Create(type)
-- NOTE: Most of the following code is copied from AceGUI-3.0/Dropdown widget
local count = AceGUI:GetNextWidgetNum(type)
local frame = CreateFrame("Button", "AceGUI30DropDownItem"..count)
local self = {}
self.frame = frame
frame.obj = self
self.type = type
self.useHighlight = true
frame:SetHeight(17)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
local text = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
text:SetTextColor(1,1,1)
text:SetJustifyH("LEFT")
text:SetPoint("TOPLEFT",frame,"TOPLEFT",18,0)
text:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-8,0)
self.text = text
local highlight = frame:CreateTexture(nil, "OVERLAY")
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
highlight:SetBlendMode("ADD")
highlight:SetHeight(14)
highlight:ClearAllPoints()
highlight:SetPoint("RIGHT",frame,"RIGHT",-3,0)
highlight:SetPoint("LEFT",frame,"LEFT",5,0)
highlight:Hide()
self.highlight = highlight
local check = frame:CreateTexture("OVERLAY")
check:SetWidth(16)
check:SetHeight(16)
check:SetPoint("LEFT",frame,"LEFT",3,-1)
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
check:Hide()
self.check = check
local sub = frame:CreateTexture("OVERLAY")
sub:SetWidth(16)
sub:SetHeight(16)
sub:SetPoint("RIGHT",frame,"RIGHT",-3,-1)
sub:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow")
sub:Hide()
self.sub = sub
frame:SetScript("OnEnter", ItemBase.Frame_OnEnter)
frame:SetScript("OnLeave", ItemBase.Frame_OnLeave)
self.OnAcquire = ItemBase.OnAcquire
self.OnRelease = ItemBase.OnRelease
self.SetPullout = ItemBase.SetPullout
self.GetText = ItemBase.GetText
self.SetText = ItemBase.SetText
self.SetDisabled = ItemBase.SetDisabled
self.SetPoint = ItemBase.SetPoint
self.Show = ItemBase.Show
self.Hide = ItemBase.Hide
self.SetOnLeave = ItemBase.SetOnLeave
self.SetOnEnter = ItemBase.SetOnEnter
return self
end
--[[
Template for items:
-- Item:
--
do
local widgetType = "Dropdown-Item-"
local widgetVersion = 1
local function Constructor()
local self = ItemBase.Create(widgetType)
AceGUI:RegisterAsWidget(self)
return self
end
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
--]]
-- Item: Header
-- A single text entry.
-- Special: Different text color and no highlight
do
local widgetType = "Dropdown-Item-Header"
local widgetVersion = 1
local function OnEnter(this)
local self = this.obj
self:Fire("OnEnter")
if self.specialOnEnter then
self.specialOnEnter(self)
end
end
local function OnLeave(this)
local self = this.obj
self:Fire("OnLeave")
if self.specialOnLeave then
self.specialOnLeave(self)
end
end
-- exported, override
local function SetDisabled(self, disabled)
ItemBase.SetDisabled(self, disabled)
if not disabled then
self.text:SetTextColor(1, 1, 0)
end
end
local function Constructor()
local self = ItemBase.Create(widgetType)
self.SetDisabled = SetDisabled
self.frame:SetScript("OnEnter", OnEnter)
self.frame:SetScript("OnLeave", OnLeave)
self.text:SetTextColor(1, 1, 0)
AceGUI:RegisterAsWidget(self)
return self
end
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
-- Item: Execute
-- A simple button
do
local widgetType = "Dropdown-Item-Execute"
local widgetVersion = 1
local function Frame_OnClick(this, button)
local self = this.obj
if self.disabled then return end
self:Fire("OnClick")
if self.pullout then
self.pullout:Close()
end
end
local function Constructor()
local self = ItemBase.Create(widgetType)
self.frame:SetScript("OnClick", Frame_OnClick)
AceGUI:RegisterAsWidget(self)
return self
end
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
-- Item: Toggle
-- Some sort of checkbox for dropdown menus.
-- Does not close the pullout on click.
do
local widgetType = "Dropdown-Item-Toggle"
local widgetVersion = 3
local function UpdateToggle(self)
if self.value then
self.check:Show()
else
self.check:Hide()
end
end
local function OnRelease(self)
ItemBase.OnRelease(self)
self:SetValue(nil)
end
local function Frame_OnClick(this, button)
local self = this.obj
if self.disabled then return end
self.value = not self.value
if self.value then
PlaySound("igMainMenuOptionCheckBoxOn")
else
PlaySound("igMainMenuOptionCheckBoxOff")
end
UpdateToggle(self)
self:Fire("OnValueChanged", self.value)
end
-- exported
local function SetValue(self, value)
self.value = value
UpdateToggle(self)
end
-- exported
local function GetValue(self)
return self.value
end
local function Constructor()
local self = ItemBase.Create(widgetType)
self.frame:SetScript("OnClick", Frame_OnClick)
self.SetValue = SetValue
self.GetValue = GetValue
self.OnRelease = OnRelease
AceGUI:RegisterAsWidget(self)
return self
end
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
-- Item: Menu
-- Shows a submenu on mouse over
-- Does not close the pullout on click
do
local widgetType = "Dropdown-Item-Menu"
local widgetVersion = 2
local function OnEnter(this)
local self = this.obj
self:Fire("OnEnter")
if self.specialOnEnter then
self.specialOnEnter(self)
end
self.highlight:Show()
if not self.disabled and self.submenu then
self.submenu:Open("TOPLEFT", self.frame, "TOPRIGHT", self.pullout:GetRightBorderWidth(), 0, self.frame:GetFrameLevel() + 100)
end
end
local function OnHide(this)
local self = this.obj
if self.submenu then
self.submenu:Close()
end
end
-- exported
local function SetMenu(self, menu)
assert(menu.type == "Dropdown-Pullout")
self.submenu = menu
end
-- exported
local function CloseMenu(self)
self.submenu:Close()
end
local function Constructor()
local self = ItemBase.Create(widgetType)
self.sub:Show()
self.frame:SetScript("OnEnter", OnEnter)
self.frame:SetScript("OnHide", OnHide)
self.SetMenu = SetMenu
self.CloseMenu = CloseMenu
AceGUI:RegisterAsWidget(self)
return self
end
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
-- Item: Separator
-- A single line to separate items
do
local widgetType = "Dropdown-Item-Separator"
local widgetVersion = 1
-- exported, override
local function SetDisabled(self, disabled)
ItemBase.SetDisabled(self, disabled)
self.useHighlight = false
end
local function Constructor()
local self = ItemBase.Create(widgetType)
self.SetDisabled = SetDisabled
local line = self.frame:CreateTexture(nil, "OVERLAY")
line:SetHeight(1)
line:SetTexture(.5, .5, .5)
line:SetPoint("LEFT", self.frame, "LEFT", 10, 0)
line:SetPoint("RIGHT", self.frame, "RIGHT", -10, 0)
self.text:Hide()
self.useHighlight = false
AceGUI:RegisterAsWidget(self)
return self
end
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end

View File

@@ -0,0 +1,707 @@
--[[ $Id: AceGUIWidget-DropDown.lua 916 2010-03-15 12:24:36Z nevcairiel $ ]]--
local AceGUI = LibStub("AceGUI-3.0")
-- Lua APIs
local min, max, floor = math.min, math.max, math.floor
local select, pairs, ipairs = select, pairs, ipairs
local tsort = table.sort
-- WoW APIs
local PlaySound = PlaySound
local UIParent, CreateFrame = UIParent, CreateFrame
local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: CLOSE
local function fixlevels(parent,...)
local i = 1
local child = select(i, ...)
while child do
child:SetFrameLevel(parent:GetFrameLevel()+1)
fixlevels(child, child:GetChildren())
i = i + 1
child = select(i, ...)
end
end
local function fixstrata(strata, parent, ...)
local i = 1
local child = select(i, ...)
parent:SetFrameStrata(strata)
while child do
fixstrata(strata, child, child:GetChildren())
i = i + 1
child = select(i, ...)
end
end
do
local widgetType = "Dropdown-Pullout"
local widgetVersion = 3
--[[ Static data ]]--
local backdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
edgeSize = 32,
tileSize = 32,
tile = true,
insets = { left = 11, right = 12, top = 12, bottom = 11 },
}
local sliderBackdrop = {
bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
tile = true, tileSize = 8, edgeSize = 8,
insets = { left = 3, right = 3, top = 3, bottom = 3 }
}
local defaultWidth = 200
local defaultMaxHeight = 600
--[[ UI Event Handlers ]]--
-- HACK: This should be no part of the pullout, but there
-- is no other 'clean' way to response to any item-OnEnter
-- Used to close Submenus when an other item is entered
local function OnEnter(item)
local self = item.pullout
for k, v in ipairs(self.items) do
if v.CloseMenu and v ~= item then
v:CloseMenu()
end
end
end
-- See the note in Constructor() for each scroll related function
local function OnMouseWheel(this, value)
this.obj:MoveScroll(value)
end
local function OnScrollValueChanged(this, value)
this.obj:SetScroll(value)
end
local function OnSizeChanged(this)
this.obj:FixScroll()
end
--[[ Exported methods ]]--
-- exported
local function SetScroll(self, value)
local status = self.scrollStatus
local frame, child = self.scrollFrame, self.itemFrame
local height, viewheight = frame:GetHeight(), child:GetHeight()
local offset
if height > viewheight then
offset = 0
else
offset = floor((viewheight - height) / 1000 * value)
end
child:ClearAllPoints()
child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", self.slider:IsShown() and -12 or 0, offset)
status.offset = offset
status.scrollvalue = value
end
-- exported
local function MoveScroll(self, value)
local status = self.scrollStatus
local frame, child = self.scrollFrame, self.itemFrame
local height, viewheight = frame:GetHeight(), child:GetHeight()
if height > viewheight then
self.slider:Hide()
else
self.slider:Show()
local diff = height - viewheight
local delta = 1
if value < 0 then
delta = -1
end
self.slider:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
end
end
-- exported
local function FixScroll(self)
local status = self.scrollStatus
local frame, child = self.scrollFrame, self.itemFrame
local height, viewheight = frame:GetHeight(), child:GetHeight()
local offset = status.offset or 0
if viewheight < height then
self.slider:Hide()
child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, offset)
self.slider:SetValue(0)
else
self.slider:Show()
local value = (offset / (viewheight - height) * 1000)
if value > 1000 then value = 1000 end
self.slider:SetValue(value)
self:SetScroll(value)
if value < 1000 then
child:ClearAllPoints()
child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -12, offset)
status.offset = offset
end
end
end
-- exported, AceGUI callback
local function OnAcquire(self)
self.frame:SetParent(UIParent)
--self.itemFrame:SetToplevel(true)
end
-- exported, AceGUI callback
local function OnRelease(self)
self:Clear()
self.frame:ClearAllPoints()
self.frame:Hide()
end
-- exported
local function AddItem(self, item)
self.items[#self.items + 1] = item
local h = #self.items * 16
self.itemFrame:SetHeight(h)
self.frame:SetHeight(min(h + 34, self.maxHeight)) -- +34: 20 for scrollFrame placement (10 offset) and +14 for item placement
item.frame:SetPoint("LEFT", self.itemFrame, "LEFT")
item.frame:SetPoint("RIGHT", self.itemFrame, "RIGHT")
item:SetPullout(self)
item:SetOnEnter(OnEnter)
end
-- exported
local function Open(self, point, relFrame, relPoint, x, y)
local items = self.items
local frame = self.frame
local itemFrame = self.itemFrame
frame:SetPoint(point, relFrame, relPoint, x, y)
local height = 8
for i, item in pairs(items) do
if i == 1 then
item:SetPoint("TOP", itemFrame, "TOP", 0, -2)
else
item:SetPoint("TOP", items[i-1].frame, "BOTTOM", 0, 1)
end
item:Show()
height = height + 16
end
itemFrame:SetHeight(height)
fixstrata("TOOLTIP", frame, frame:GetChildren())
frame:Show()
self:Fire("OnOpen")
end
-- exported
local function Close(self)
self.frame:Hide()
self:Fire("OnClose")
end
-- exported
local function Clear(self)
local items = self.items
for i, item in pairs(items) do
AceGUI:Release(item)
items[i] = nil
end
end
-- exported
local function IterateItems(self)
return ipairs(self.items)
end
-- exported
local function SetHideOnLeave(self, val)
self.hideOnLeave = val
end
-- exported
local function SetMaxHeight(self, height)
self.maxHeight = height or defaultMaxHeight
if self.frame:GetHeight() > height then
self.frame:SetHeight(height)
elseif (self.itemFrame:GetHeight() + 34) < height then
self.frame:SetHeight(self.itemFrame:GetHeight() + 34) -- see :AddItem
end
end
-- exported
local function GetRightBorderWidth(self)
return 6 + (self.slider:IsShown() and 12 or 0)
end
-- exported
local function GetLeftBorderWidth(self)
return 6
end
--[[ Constructor ]]--
local function Constructor()
local count = AceGUI:GetNextWidgetNum(widgetType)
local frame = CreateFrame("Frame", "AceGUI30Pullout"..count, UIParent)
local self = {}
self.count = count
self.type = widgetType
self.frame = frame
frame.obj = self
self.OnAcquire = OnAcquire
self.OnRelease = OnRelease
self.AddItem = AddItem
self.Open = Open
self.Close = Close
self.Clear = Clear
self.IterateItems = IterateItems
self.SetHideOnLeave = SetHideOnLeave
self.SetScroll = SetScroll
self.MoveScroll = MoveScroll
self.FixScroll = FixScroll
self.SetMaxHeight = SetMaxHeight
self.GetRightBorderWidth = GetRightBorderWidth
self.GetLeftBorderWidth = GetLeftBorderWidth
self.items = {}
self.scrollStatus = {
scrollvalue = 0,
}
self.maxHeight = defaultMaxHeight
frame:SetBackdrop(backdrop)
frame:SetBackdropColor(0, 0, 0)
frame:SetFrameStrata("FULLSCREEN_DIALOG")
frame:SetClampedToScreen(true)
frame:SetWidth(defaultWidth)
frame:SetHeight(self.maxHeight)
--frame:SetToplevel(true)
-- NOTE: The whole scroll frame code is copied from the AceGUI-3.0 widget ScrollFrame
local scrollFrame = CreateFrame("ScrollFrame", nil, frame)
local itemFrame = CreateFrame("Frame", nil, scrollFrame)
self.scrollFrame = scrollFrame
self.itemFrame = itemFrame
scrollFrame.obj = self
itemFrame.obj = self
local slider = CreateFrame("Slider", "AceGUI30PulloutScrollbar"..count, scrollFrame)
slider:SetOrientation("VERTICAL")
slider:SetHitRectInsets(0, 0, -10, 0)
slider:SetBackdrop(sliderBackdrop)
slider:SetWidth(8)
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
slider:SetFrameStrata("FULLSCREEN_DIALOG")
self.slider = slider
slider.obj = self
scrollFrame:SetScrollChild(itemFrame)
scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -12)
scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 12)
scrollFrame:EnableMouseWheel(true)
scrollFrame:SetScript("OnMouseWheel", OnMouseWheel)
scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
scrollFrame:SetToplevel(true)
scrollFrame:SetFrameStrata("FULLSCREEN_DIALOG")
itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0)
itemFrame:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", -12, 0)
itemFrame:SetHeight(400)
itemFrame:SetToplevel(true)
itemFrame:SetFrameStrata("FULLSCREEN_DIALOG")
slider:SetPoint("TOPLEFT", scrollFrame, "TOPRIGHT", -16, 0)
slider:SetPoint("BOTTOMLEFT", scrollFrame, "BOTTOMRIGHT", -16, 0)
slider:SetScript("OnValueChanged", OnScrollValueChanged)
slider:SetMinMaxValues(0, 1000)
slider:SetValueStep(1)
slider:SetValue(0)
scrollFrame:Show()
itemFrame:Show()
slider:Hide()
self:FixScroll()
AceGUI:RegisterAsWidget(self)
return self
end
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
end
do
local widgetType = "Dropdown"
local widgetVersion = 22
--[[ Static data ]]--
--[[ UI event handler ]]--
local function Control_OnEnter(this)
this.obj:Fire("OnEnter")
end
local function Control_OnLeave(this)
this.obj:Fire("OnLeave")
end
local function Dropdown_OnHide(this)
local self = this.obj
if self.open then
self.pullout:Close()
end
end
local function Dropdown_TogglePullout(this)
local self = this.obj
PlaySound("igMainMenuOptionCheckBoxOn") -- missleading name, but the Blizzard code uses this sound
if self.open then
self.open = nil
self.pullout:Close()
AceGUI:ClearFocus()
else
self.open = true
self.pullout:SetWidth(self.frame:GetWidth())
self.pullout:Open("TOPLEFT", self.frame, "BOTTOMLEFT", 0, self.label:IsShown() and -2 or 0)
AceGUI:SetFocus(self)
end
end
local function OnPulloutOpen(this)
local self = this.userdata.obj
local value = self.value
if not self.multiselect then
for i, item in this:IterateItems() do
item:SetValue(item.userdata.value == value)
end
end
self.open = true
end
local function OnPulloutClose(this)
local self = this.userdata.obj
self.open = nil
self:Fire("OnClosed")
end
local function ShowMultiText(self)
local text
for i, widget in self.pullout:IterateItems() do
if widget.type == "Dropdown-Item-Toggle" then
if widget:GetValue() then
if text then
text = text..", "..widget:GetText()
else
text = widget:GetText()
end
end
end
end
self:SetText(text)
end
local function OnItemValueChanged(this, event, checked)
local self = this.userdata.obj
if self.multiselect then
self:Fire("OnValueChanged", this.userdata.value, checked)
ShowMultiText(self)
else
if checked then
self:SetValue(this.userdata.value)
self:Fire("OnValueChanged", this.userdata.value)
else
this:SetValue(true)
end
if self.open then
self.pullout:Close()
end
end
end
--[[ Exported methods ]]--
-- exported, AceGUI callback
local function OnAcquire(self)
local pullout = AceGUI:Create("Dropdown-Pullout")
self.pullout = pullout
pullout.userdata.obj = self
pullout:SetCallback("OnClose", OnPulloutClose)
pullout:SetCallback("OnOpen", OnPulloutOpen)
self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1)
fixlevels(self.pullout.frame, self.pullout.frame:GetChildren())
self:SetHeight(44)
self:SetWidth(200)
end
-- exported, AceGUI callback
local function OnRelease(self)
if self.open then
self.pullout:Close()
end
AceGUI:Release(self.pullout)
self.pullout = nil
self:SetText("")
self:SetLabel("")
self:SetDisabled(false)
self:SetMultiselect(false)
self.value = nil
self.list = nil
self.open = nil
self.hasClose = nil
self.frame:ClearAllPoints()
self.frame:Hide()
end
-- exported
local function SetDisabled(self, disabled)
self.disabled = disabled
if disabled then
self.text:SetTextColor(0.5,0.5,0.5)
self.button:Disable()
self.label:SetTextColor(0.5,0.5,0.5)
else
self.button:Enable()
self.label:SetTextColor(1,.82,0)
self.text:SetTextColor(1,1,1)
end
end
-- exported
local function ClearFocus(self)
if self.open then
self.pullout:Close()
end
end
-- exported
local function SetText(self, text)
self.text:SetText(text or "")
end
-- exported
local function SetLabel(self, text)
if text and text ~= "" then
self.label:SetText(text)
self.label:Show()
self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,-18)
self.frame:SetHeight(44)
else
self.label:SetText("")
self.label:Hide()
self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,0)
self.frame:SetHeight(26)
end
end
-- exported
local function SetValue(self, value)
if self.list then
self:SetText(self.list[value] or "")
end
self.value = value
end
-- exported
local function GetValue(self)
return self.value
end
-- exported
local function SetItemValue(self, item, value)
if not self.multiselect then return end
for i, widget in self.pullout:IterateItems() do
if widget.userdata.value == item then
if widget.SetValue then
widget:SetValue(value)
end
end
end
ShowMultiText(self)
end
-- exported
local function SetItemDisabled(self, item, disabled)
for i, widget in self.pullout:IterateItems() do
if widget.userdata.value == item then
widget:SetDisabled(disabled)
end
end
end
local function AddListItem(self, value, text)
local item = AceGUI:Create("Dropdown-Item-Toggle")
item:SetText(text)
item.userdata.obj = self
item.userdata.value = value
item:SetCallback("OnValueChanged", OnItemValueChanged)
self.pullout:AddItem(item)
end
local function AddCloseButton(self)
if not self.hasClose then
local close = AceGUI:Create("Dropdown-Item-Execute")
close:SetText(CLOSE)
self.pullout:AddItem(close)
self.hasClose = true
end
end
-- exported
local sortlist = {}
local function SetList(self, list)
self.list = list
self.pullout:Clear()
self.hasClose = nil
if not list then return end
for v in pairs(list) do
sortlist[#sortlist + 1] = v
end
tsort(sortlist)
for i, value in pairs(sortlist) do
AddListItem(self, value, list[value])
sortlist[i] = nil
end
if self.multiselect then
ShowMultiText(self)
AddCloseButton(self)
end
end
-- exported
local function AddItem(self, value, text)
if self.list then
self.list[value] = text
AddListItem(self, value, text)
end
end
-- exported
local function SetMultiselect(self, multi)
self.multiselect = multi
if multi then
ShowMultiText(self)
AddCloseButton(self)
end
end
-- exported
local function GetMultiselect(self)
return self.multiselect
end
--[[ Constructor ]]--
local function Constructor()
local count = AceGUI:GetNextWidgetNum(widgetType)
local frame = CreateFrame("Frame", nil, UIParent)
local dropdown = CreateFrame("Frame", "AceGUI30DropDown"..count, frame, "UIDropDownMenuTemplate")
local self = {}
self.type = widgetType
self.frame = frame
self.dropdown = dropdown
self.count = count
frame.obj = self
dropdown.obj = self
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
self.ClearFocus = ClearFocus
self.SetText = SetText
self.SetValue = SetValue
self.GetValue = GetValue
self.SetList = SetList
self.SetLabel = SetLabel
self.SetDisabled = SetDisabled
self.AddItem = AddItem
self.SetMultiselect = SetMultiselect
self.GetMultiselect = GetMultiselect
self.SetItemValue = SetItemValue
self.SetItemDisabled = SetItemDisabled
self.alignoffset = 31
frame:SetHeight(44)
frame:SetWidth(200)
frame:SetScript("OnHide",Dropdown_OnHide)
dropdown:ClearAllPoints()
dropdown:SetPoint("TOPLEFT",frame,"TOPLEFT",-15,0)
dropdown:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",17,0)
dropdown:SetScript("OnHide", nil)
local left = _G[dropdown:GetName() .. "Left"]
local middle = _G[dropdown:GetName() .. "Middle"]
local right = _G[dropdown:GetName() .. "Right"]
middle:ClearAllPoints()
right:ClearAllPoints()
middle:SetPoint("LEFT", left, "RIGHT", 0, 0)
middle:SetPoint("RIGHT", right, "LEFT", 0, 0)
right:SetPoint("TOPRIGHT", dropdown, "TOPRIGHT", 0, 17)
local button = _G[dropdown:GetName() .. "Button"]
self.button = button
button.obj = self
button:SetScript("OnEnter",Control_OnEnter)
button:SetScript("OnLeave",Control_OnLeave)
button:SetScript("OnClick",Dropdown_TogglePullout)
local text = _G[dropdown:GetName() .. "Text"]
self.text = text
text.obj = self
text:ClearAllPoints()
text:SetPoint("RIGHT", right, "RIGHT" ,-43, 2)
text:SetPoint("LEFT", left, "LEFT", 25, 2)
local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
label:SetJustifyH("LEFT")
label:SetHeight(18)
label:Hide()
self.label = label
AceGUI:RegisterAsWidget(self)
return self
end
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
end

View File

@@ -0,0 +1,235 @@
--[[-----------------------------------------------------------------------------
EditBox Widget
-------------------------------------------------------------------------------]]
local Type, Version = "EditBox", 22
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local tostring, pairs = tostring, pairs
-- WoW APIs
local PlaySound = PlaySound
local GetCursorInfo, ClearCursor, GetSpellName = GetCursorInfo, ClearCursor, GetSpellName
local CreateFrame, UIParent = CreateFrame, UIParent
local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: AceGUIEditBoxInsertLink, ChatFontNormal, OKAY
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
if not AceGUIEditBoxInsertLink then
-- upgradeable hook
hooksecurefunc("ChatEdit_InsertLink", function(...) return _G.AceGUIEditBoxInsertLink(...) end)
end
function _G.AceGUIEditBoxInsertLink(text)
for i = 1, AceGUI:GetWidgetCount(Type) do
local editbox = _G["AceGUI-3.0EditBox"..i]
if editbox and editbox:IsVisible() and editbox:HasFocus() then
editbox:Insert(text)
return true
end
end
end
local function ShowButton(self)
if not self.disablebutton then
self.button:Show()
self.editbox:SetTextInsets(0, 20, 3, 3)
end
end
local function HideButton(self)
self.button:Hide()
self.editbox:SetTextInsets(0, 0, 3, 3)
end
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
local function EditBox_OnEscapePressed(frame)
AceGUI:ClearFocus()
end
local function EditBox_OnEnterPressed(frame)
local self = frame.obj
local value = frame:GetText()
local cancel = self:Fire("OnEnterPressed", value)
if not cancel then
PlaySound("igMainMenuOptionCheckBoxOn")
HideButton(self)
end
end
local function EditBox_OnReceiveDrag(frame)
local self = frame.obj
local type, id, info = GetCursorInfo()
if type == "item" then
self:SetText(info)
self:Fire("OnEnterPressed", info)
ClearCursor()
elseif type == "spell" then
local name, rank = GetSpellName(id, info)
if rank and rank:match("%d") then
name = name.."("..rank..")"
end
self:SetText(name)
self:Fire("OnEnterPressed", name)
ClearCursor()
end
HideButton(self)
AceGUI:ClearFocus()
end
local function EditBox_OnTextChanged(frame)
local self = frame.obj
local value = frame:GetText()
if tostring(value) ~= tostring(self.lasttext) then
self:Fire("OnTextChanged", value)
self.lasttext = value
ShowButton(self)
end
end
local function Button_OnClick(frame)
local editbox = frame.obj.editbox
editbox:ClearFocus()
EditBox_OnEnterPressed(editbox)
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
-- height is controlled by SetLabel
self:SetWidth(200)
self:SetDisabled(false)
self:SetLabel()
self:SetText()
self:DisableButton(false)
self:SetMaxLetters(0)
end,
-- ["OnRelease"] = nil,
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if disabled then
self.editbox:EnableMouse(false)
self.editbox:ClearFocus()
self.editbox:SetTextColor(0.5,0.5,0.5)
self.label:SetTextColor(0.5,0.5,0.5)
else
self.editbox:EnableMouse(true)
self.editbox:SetTextColor(1,1,1)
self.label:SetTextColor(1,.82,0)
end
end,
["SetText"] = function(self, text)
self.lasttext = text or ""
self.editbox:SetText(text or "")
self.editbox:SetCursorPosition(0)
HideButton(self)
end,
["GetText"] = function(self, text)
return self.editbox:GetText()
end,
["SetLabel"] = function(self, text)
if text and text ~= "" then
self.label:SetText(text)
self.label:Show()
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,-18)
self:SetHeight(44)
self.alignoffset = 30
else
self.label:SetText("")
self.label:Hide()
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,0)
self:SetHeight(26)
self.alignoffset = 12
end
end,
["DisableButton"] = function(self, disabled)
self.disablebutton = disabled
if disabled then
HideButton(self)
end
end,
["SetMaxLetters"] = function (self, num)
self.editbox:SetMaxLetters(num or 0)
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local num = AceGUI:GetNextWidgetNum(Type)
local frame = CreateFrame("Frame", nil, UIParent)
frame:Hide()
local editbox = CreateFrame("EditBox", "AceGUI-3.0EditBox"..num, frame, "InputBoxTemplate")
editbox:SetAutoFocus(false)
editbox:SetFontObject(ChatFontNormal)
editbox:SetScript("OnEnter", Control_OnEnter)
editbox:SetScript("OnLeave", Control_OnLeave)
editbox:SetScript("OnEscapePressed", EditBox_OnEscapePressed)
editbox:SetScript("OnEnterPressed", EditBox_OnEnterPressed)
editbox:SetScript("OnTextChanged", EditBox_OnTextChanged)
editbox:SetScript("OnReceiveDrag", EditBox_OnReceiveDrag)
editbox:SetScript("OnMouseDown", EditBox_OnReceiveDrag)
editbox:SetTextInsets(0, 0, 3, 3)
editbox:SetMaxLetters(256)
editbox:SetPoint("BOTTOMLEFT", 6, 0)
editbox:SetPoint("BOTTOMRIGHT")
editbox:SetHeight(19)
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
label:SetPoint("TOPLEFT", 0, -2)
label:SetPoint("TOPRIGHT", 0, -2)
label:SetJustifyH("LEFT")
label:SetHeight(18)
local button = CreateFrame("Button", nil, editbox, "UIPanelButtonTemplate")
button:SetWidth(40)
button:SetHeight(20)
button:SetPoint("RIGHT", -2, 0)
button:SetText(OKAY)
button:SetScript("OnClick", Button_OnClick)
button:Hide()
local widget = {
alignoffset = 30,
editbox = editbox,
label = label,
button = button,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
editbox.obj, button.obj = widget, widget
return AceGUI:RegisterAsWidget(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,78 @@
--[[-----------------------------------------------------------------------------
Heading Widget
-------------------------------------------------------------------------------]]
local Type, Version = "Heading", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local pairs = pairs
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetText()
self:SetFullWidth()
self:SetHeight(18)
end,
-- ["OnRelease"] = nil,
["SetText"] = function(self, text)
self.label:SetText(text or "")
if text and text ~= "" then
self.left:SetPoint("RIGHT", self.label, "LEFT", -5, 0)
self.right:Show()
else
self.left:SetPoint("RIGHT", -3, 0)
self.right:Hide()
end
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:Hide()
local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
label:SetPoint("TOP")
label:SetPoint("BOTTOM")
label:SetJustifyH("CENTER")
local left = frame:CreateTexture(nil, "BACKGROUND")
left:SetHeight(8)
left:SetPoint("LEFT", 3, 0)
left:SetPoint("RIGHT", label, "LEFT", -5, 0)
left:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
left:SetTexCoord(0.81, 0.94, 0.5, 1)
local right = frame:CreateTexture(nil, "BACKGROUND")
right:SetHeight(8)
right:SetPoint("RIGHT", -3, 0)
right:SetPoint("LEFT", label, "RIGHT", 5, 0)
right:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
right:SetTexCoord(0.81, 0.94, 0.5, 1)
local widget = {
label = label,
left = left,
right = right,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
return AceGUI:RegisterAsWidget(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,144 @@
--[[-----------------------------------------------------------------------------
Icon Widget
-------------------------------------------------------------------------------]]
local Type, Version = "Icon", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local select, pairs, print = select, pairs, print
-- WoW APIs
local CreateFrame, UIParent, GetBuildInfo = CreateFrame, UIParent, GetBuildInfo
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
local function Button_OnClick(frame, button)
frame.obj:Fire("OnClick", button)
AceGUI:ClearFocus()
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetHeight(110)
self:SetWidth(110)
self:SetLabel()
self:SetImage(nil)
self:SetImageSize(64, 64)
self:SetDisabled(false)
end,
-- ["OnRelease"] = nil,
["SetLabel"] = function(self, text)
if text and text ~= "" then
self.label:Show()
self.label:SetText(text)
self:SetHeight(self.image:GetHeight() + 25)
else
self.label:Hide()
self:SetHeight(self.image:GetHeight() + 10)
end
end,
["SetImage"] = function(self, path, ...)
local image = self.image
image:SetTexture(path)
if image:GetTexture() then
local n = select("#", ...)
if n == 4 or n == 8 then
image:SetTexCoord(...)
else
image:SetTexCoord(0, 1, 0, 1)
end
end
end,
["SetImageSize"] = function(self, width, height)
self.image:SetWidth(width)
self.image:SetHeight(height)
--self.frame:SetWidth(width + 30)
if self.label:IsShown() then
self:SetHeight(height + 25)
else
self:SetHeight(height + 10)
end
end,
["SetDisabled"] = function(self, disabled)
self.disabled = disabled
if disabled then
self.frame:Disable()
self.label:SetTextColor(0.5, 0.5, 0.5)
self.image:SetVertexColor(0.5, 0.5, 0.5, 0.5)
else
self.frame:Enable()
self.label:SetTextColor(1, 1, 1)
self.image:SetVertexColor(1, 1, 1)
end
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Button", nil, UIParent)
frame:Hide()
frame:EnableMouse(true)
frame:SetScript("OnEnter", Control_OnEnter)
frame:SetScript("OnLeave", Control_OnLeave)
frame:SetScript("OnClick", Button_OnClick)
local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlight")
label:SetPoint("BOTTOMLEFT")
label:SetPoint("BOTTOMRIGHT")
label:SetJustifyH("CENTER")
label:SetJustifyV("TOP")
label:SetHeight(18)
local image = frame:CreateTexture(nil, "BACKGROUND")
image:SetWidth(64)
image:SetHeight(64)
image:SetPoint("TOP", 0, -5)
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
highlight:SetAllPoints(image)
highlight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight")
highlight:SetTexCoord(0, 1, 0.23, 0.77)
highlight:SetBlendMode("ADD")
local widget = {
label = label,
image = image,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
-- SetText is deprecated, but keep it around for a while. (say, to WoW 4.0)
if (select(4, GetBuildInfo()) < 40000) then
widget.SetText = widget.SetLabel
else
widget.SetText = function(self, ...) print("AceGUI-3.0-Icon: SetText is deprecated! Use SetLabel instead!"); self:SetLabel(...) end
end
return AceGUI:RegisterAsWidget(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,101 @@
--[[-----------------------------------------------------------------------------
InteractiveLabel Widget
-------------------------------------------------------------------------------]]
local Type, Version = "InteractiveLabel", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local select, pairs = select, pairs
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GameFontHighlightSmall
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
local function Label_OnClick(frame, button)
frame.obj:Fire("OnClick", button)
AceGUI:ClearFocus()
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:LabelOnAcquire()
self:SetHighlight()
self:SetHighlightTexCoord()
self:SetDisabled(false)
end,
-- ["OnRelease"] = nil,
["SetHighlight"] = function(self, ...)
self.highlight:SetTexture(...)
end,
["SetHighlightTexCoord"] = function(self, ...)
local c = select("#", ...)
if c == 4 or c == 8 then
self.highlight:SetTexCoord(...)
else
self.highlight:SetTexCoord(0, 1, 0, 1)
end
end,
["SetDisabled"] = function(self,disabled)
self.disabled = disabled
if disabled then
self.frame:EnableMouse(false)
self.label:SetTextColor(0.5, 0.5, 0.5)
else
self.frame:EnableMouse(true)
self.label:SetTextColor(1, 1, 1)
end
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
-- create a Label type that we will hijack
local label = AceGUI:Create("Label")
local frame = label.frame
frame:EnableMouse(true)
frame:SetScript("OnEnter", Control_OnEnter)
frame:SetScript("OnLeave", Control_OnLeave)
frame:SetScript("OnMouseDown", Label_OnClick)
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
highlight:SetTexture(nil)
highlight:SetAllPoints()
highlight:SetBlendMode("ADD")
label.highlight = highlight
label.type = Type
label.LabelOnAcquire = label.OnAcquire
for method, func in pairs(methods) do
label[method] = func
end
return label
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,230 @@
--[[-----------------------------------------------------------------------------
Keybinding Widget
Set Keybindings in the Config UI.
-------------------------------------------------------------------------------]]
local Type, Version = "Keybinding", 21
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local pairs = pairs
-- WoW APIs
local IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown = IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown
local CreateFrame, UIParent = CreateFrame, UIParent
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: NOT_BOUND
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
local function Keybinding_OnClick(frame, button)
if button == "LeftButton" or button == "RightButton" then
local self = frame.obj
if self.waitingForKey then
frame:EnableKeyboard(false)
self.msgframe:Hide()
frame:UnlockHighlight()
self.waitingForKey = nil
else
frame:EnableKeyboard(true)
self.msgframe:Show()
frame:LockHighlight()
self.waitingForKey = true
end
end
AceGUI:ClearFocus()
end
local ignoreKeys = {
["BUTTON1"] = true, ["BUTTON2"] = true,
["UNKNOWN"] = true,
["LSHIFT"] = true, ["LCTRL"] = true, ["LALT"] = true,
["RSHIFT"] = true, ["RCTRL"] = true, ["RALT"] = true,
}
local function Keybinding_OnKeyDown(frame, key)
local self = frame.obj
if self.waitingForKey then
local keyPressed = key
if keyPressed == "ESCAPE" then
keyPressed = ""
else
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
frame:EnableKeyboard(false)
self.msgframe:Hide()
frame:UnlockHighlight()
self.waitingForKey = nil
if not self.disabled then
self:SetKey(keyPressed)
self:Fire("OnKeyChanged", keyPressed)
end
end
end
local function Keybinding_OnMouseDown(frame, 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(frame, button)
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetWidth(200)
self:SetLabel("")
self:SetKey("")
self.waitingForKey = nil
self.msgframe:Hide()
self:SetDisabled(false)
end,
-- ["OnRelease"] = nil,
["SetDisabled"] = function(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,
["SetKey"] = function(self, key)
if (key or "") == "" then
self.button:SetText(NOT_BOUND)
self.button:SetNormalFontObject("GameFontNormal")
else
self.button:SetText(key)
self.button:SetNormalFontObject("GameFontHighlight")
end
end,
["GetKey"] = function(self)
local key = self.button:GetText()
if key == NOT_BOUND then
key = nil
end
return key
end,
["SetLabel"] = function(self, label)
self.label:SetText(label or "")
if (label or "") == "" then
self.alignoffset = nil
self:SetHeight(24)
else
self.alignoffset = 30
self:SetHeight(44)
end
end,
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
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 keybindingMsgFixWidth(frame)
frame:SetWidth(frame.msg:GetWidth() + 10)
frame:SetScript("OnUpdate", nil)
end
local function Constructor()
local name = "AceGUI30KeybindingButton" .. AceGUI:GetNextWidgetNum(Type)
local frame = CreateFrame("Frame", nil, UIParent)
local button = CreateFrame("Button", name, frame, "UIPanelButtonTemplate2")
button:EnableMouse(true)
button:RegisterForClicks("AnyDown")
button:SetScript("OnEnter", Control_OnEnter)
button:SetScript("OnLeave", Control_OnLeave)
button:SetScript("OnClick", Keybinding_OnClick)
button:SetScript("OnKeyDown", Keybinding_OnKeyDown)
button:SetScript("OnMouseDown", Keybinding_OnMouseDown)
button:SetPoint("BOTTOMLEFT")
button:SetPoint("BOTTOMRIGHT")
button:SetHeight(24)
local text = button:GetFontString()
text:SetPoint("LEFT", 7, 0)
text:SetPoint("RIGHT", -7, 0)
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
label:SetPoint("TOPLEFT")
label:SetPoint("TOPRIGHT")
label:SetJustifyH("CENTER")
label:SetHeight(18)
local msgframe = CreateFrame("Frame", nil, UIParent)
msgframe:SetHeight(30)
msgframe:SetBackdrop(ControlBackdrop)
msgframe:SetBackdropColor(0,0,0)
msgframe:SetFrameStrata("FULLSCREEN_DIALOG")
msgframe:SetFrameLevel(1000)
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", 5, -5)
msgframe:SetScript("OnUpdate", keybindingMsgFixWidth)
msgframe:SetPoint("BOTTOM", button, "TOP")
msgframe:Hide()
local widget = {
button = button,
label = label,
msgframe = msgframe,
frame = frame,
alignoffset = 30,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
button.obj = widget
return AceGUI:RegisterAsWidget(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,162 @@
--[[-----------------------------------------------------------------------------
Label Widget
Displays text and optionally an icon.
-------------------------------------------------------------------------------]]
local Type, Version = "Label", 21
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local max, select, pairs = math.max, select, pairs
-- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GameFontHighlightSmall
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function UpdateImageAnchor(self)
if self.resizing then return end
local frame = self.frame
local width = frame.width or frame:GetWidth() or 0
local image = self.image
local label = self.label
local height
label:ClearAllPoints()
image:ClearAllPoints()
if self.imageshown then
local imagewidth = image:GetWidth()
if (width - imagewidth) < 200 or (label:GetText() or "") == "" then
-- image goes on top centered when less than 200 width for the text, or if there is no text
image:SetPoint("TOP")
label:SetPoint("TOP", image, "BOTTOM")
label:SetPoint("LEFT")
label:SetWidth(width)
height = image:GetHeight() + label:GetHeight()
else
-- image on the left
image:SetPoint("TOPLEFT")
label:SetPoint("TOPLEFT", image, "TOPRIGHT", 4, 0)
label:SetWidth(width - imagewidth - 4)
height = max(image:GetHeight(), label:GetHeight())
end
else
-- no image shown
label:SetPoint("TOPLEFT")
label:SetWidth(width)
height = label:GetHeight()
end
self.resizing = true
frame:SetHeight(height)
frame.height = height
self.resizing = nil
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
-- set the flag to stop constant size updates
self.resizing = true
-- height is set dynamically by the text and image size
self:SetWidth(200)
self:SetText()
self:SetImage(nil)
self:SetImageSize(16, 16)
self:SetColor()
self:SetFontObject()
-- reset the flag
self.resizing = nil
-- run the update explicitly
UpdateImageAnchor(self)
end,
-- ["OnRelease"] = nil,
["OnWidthSet"] = function(self, width)
UpdateImageAnchor(self)
end,
["SetText"] = function(self, text)
self.label:SetText(text)
UpdateImageAnchor(self)
end,
["SetColor"] = function(self, r, g, b)
if not (r and g and b) then
r, g, b = 1, 1, 1
end
self.label:SetVertexColor(r, g, b)
end,
["SetImage"] = function(self, path, ...)
local image = self.image
image:SetTexture(path)
if image:GetTexture() then
self.imageshown = true
local n = select("#", ...)
if n == 4 or n == 8 then
image:SetTexCoord(...)
else
image:SetTexCoord(0, 1, 0, 1)
end
else
self.imageshown = nil
end
UpdateImageAnchor(self)
end,
["SetFont"] = function(self, font, height, flags)
self.label:SetFont(font, height, flags)
end,
["SetFontObject"] = function(self, font)
self:SetFont((font or GameFontHighlightSmall):GetFont())
end,
["SetImageSize"] = function(self, width, height)
self.image:SetWidth(width)
self.image:SetHeight(height)
UpdateImageAnchor(self)
end,
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:Hide()
local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlightSmall")
label:SetJustifyH("LEFT")
label:SetJustifyV("TOP")
local image = frame:CreateTexture(nil, "BACKGROUND")
-- create widget
local widget = {
label = label,
image = image,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
return AceGUI:RegisterAsWidget(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,311 @@
local Type, Version = "MultiLineEditBox", 23
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local pairs = pairs
-- WoW APIs
local GetCursorInfo, GetSpellName, ClearCursor = GetCursorInfo, GetSpellName, ClearCursor
local CreateFrame, UIParent = CreateFrame, UIParent
local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: ACCEPT, ChatFontNormal
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function Layout(self)
self:SetHeight(self.numlines * 14 + (self.disablebutton and 19 or 41) + self.labelHeight)
if self.labelHeight == 0 then
self.scrollBar:SetPoint("TOP", self.frame, "TOP", 0, -23)
else
self.scrollBar:SetPoint("TOP", self.label, "BOTTOM", 0, -19)
end
if self.disablebutton then
self.scrollBar:SetPoint("BOTTOM", self.frame, "BOTTOM", 0, 21)
self.scrollBG:SetPoint("BOTTOMLEFT", 0, 4)
else
self.scrollBar:SetPoint("BOTTOM", self.button, "TOP", 0, 18)
self.scrollBG:SetPoint("BOTTOMLEFT", self.button, "TOPLEFT")
end
end
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function OnClick(self) -- Button
self = self.obj
self.editBox:ClearFocus()
if not self:Fire("OnEnterPressed", self.editBox:GetText()) then
self.button:Disable()
end
end
local function OnCursorChanged(self, _, y, _, cursorHeight) -- EditBox
self, y = self.obj.scrollFrame, -y
local offset = self:GetVerticalScroll()
if y < offset then
self:SetVerticalScroll(y)
else
y = y + cursorHeight - self:GetHeight()
if y > offset then
self:SetVerticalScroll(y)
end
end
end
local function OnEditFocusLost(self) -- EditBox
self:HighlightText(0, 0)
end
local function OnEnter(self) -- EditBox / ScrollFrame
self = self.obj
if not self.entered then
self.entered = true
self:Fire("OnEnter")
end
end
local function OnLeave(self) -- EditBox / ScrollFrame
self = self.obj
if self.entered then
self.entered = nil
self:Fire("OnLeave")
end
end
local function OnMouseUp(self) -- ScrollFrame
self = self.obj.editBox
self:SetFocus()
self:SetCursorPosition(self:GetNumLetters())
end
local function OnReceiveDrag(self) -- EditBox / ScrollFrame
local type, id, info = GetCursorInfo()
if type == "spell" then
info, id = GetSpellName(id, info)
if id and id:match("%d") then
info = info .. "(" .. id .. ")"
end
elseif type ~= "item" then
return
end
ClearCursor()
self = self.obj
local editBox = self.editBox
if not editBox:HasFocus() then
editBox:SetFocus()
editBox:SetCursorPosition(editBox:GetNumLetters())
end
editBox:Insert(info)
self.button:Enable()
end
local function OnSizeChanged(self, width, height) -- ScrollFrame
self.obj.editBox:SetWidth(width)
end
local function OnTextChanged(self, userInput) -- EditBox
if userInput then
self = self.obj
self:Fire("OnTextChanged", self.editBox:GetText())
self.button:Enable()
end
end
local function OnTextSet(self) -- EditBox
self:HighlightText(0, 0)
self:SetCursorPosition(self:GetNumLetters())
self:SetCursorPosition(0)
self.obj.button:Disable()
end
local function OnVerticalScroll(self, offset) -- ScrollFrame
local editBox = self.obj.editBox
editBox:SetHitRectInsets(0, 0, offset, editBox:GetHeight() - offset - self:GetHeight())
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self.editBox:SetText("")
self:SetDisabled(false)
self:SetWidth(200)
self:DisableButton(false)
self:SetNumLines()
self.entered = nil
self:SetMaxLetters(0)
end,
-- ["OnRelease"] = nil,
["SetDisabled"] = function(self, disabled)
local editBox = self.editBox
if disabled then
editBox:ClearFocus()
editBox:EnableMouse(false)
editBox:SetTextColor(0.5, 0.5, 0.5)
self.label:SetTextColor(0.5, 0.5, 0.5)
self.scrollFrame:EnableMouse(false)
self.button:Disable()
else
editBox:EnableMouse(true)
editBox:SetTextColor(1, 1, 1)
self.label:SetTextColor(1, 0.82, 0)
self.scrollFrame:EnableMouse(true)
end
end,
["SetLabel"] = function(self, text)
if text and text ~= "" then
self.label:SetText(text)
if self.labelHeight ~= 10 then
self.labelHeight = 10
self.label:Show()
end
elseif self.labelHeight ~= 0 then
self.labelHeight = 0
self.label:Hide()
end
Layout(self)
end,
["SetNumLines"] = function(self, value)
if not value or value < 4 then
value = 4
end
self.numlines = value
Layout(self)
end,
["SetText"] = function(self, text)
self.editBox:SetText(text)
end,
["GetText"] = function(self)
return self.editBox:GetText()
end,
["SetMaxLetters"] = function (self, num)
self.editBox:SetMaxLetters(num or 0)
end,
["DisableButton"] = function(self, disabled)
self.disablebutton = disabled
if disabled then
self.button:Hide()
else
self.button:Show()
end
Layout(self)
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local backdrop = {
bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeSize = 16,
insets = { left = 4, right = 3, top = 4, bottom = 3 }
}
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:Hide()
local widgetNum = AceGUI:GetNextWidgetNum(Type)
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
label:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, -4)
label:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -4)
label:SetJustifyH("LEFT")
label:SetText(ACCEPT)
label:SetHeight(10)
local button = CreateFrame("Button", ("%s%dButton"):format(Type, widgetNum), frame, "UIPanelButtonTemplate2")
button:SetPoint("BOTTOMLEFT", 0, 4)
button:SetHeight(22)
button:SetWidth(label:GetStringWidth() + 24)
button:SetText(ACCEPT)
button:SetScript("OnClick", OnClick)
button:Disable()
local text = button:GetFontString()
text:ClearAllPoints()
text:SetPoint("TOPLEFT", button, "TOPLEFT", 5, -5)
text:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -5, 1)
text:SetJustifyV("MIDDLE")
local scrollBG = CreateFrame("Frame", nil, frame)
scrollBG:SetBackdrop(backdrop)
scrollBG:SetBackdropColor(0, 0, 0)
scrollBG:SetBackdropBorderColor(0.4, 0.4, 0.4)
local scrollFrame = CreateFrame("ScrollFrame", ("%s%dScrollFrame"):format(Type, widgetNum), frame, "UIPanelScrollFrameTemplate")
local scrollBar = _G[scrollFrame:GetName() .. "ScrollBar"]
scrollBar:ClearAllPoints()
scrollBar:SetPoint("TOP", label, "BOTTOM", 0, -19)
scrollBar:SetPoint("BOTTOM", button, "TOP", 0, 18)
scrollBar:SetPoint("RIGHT", frame, "RIGHT")
scrollBG:SetPoint("TOPRIGHT", scrollBar, "TOPLEFT", 0, 19)
scrollBG:SetPoint("BOTTOMLEFT", button, "TOPLEFT")
scrollFrame:SetPoint("TOPLEFT", scrollBG, "TOPLEFT", 5, -6)
scrollFrame:SetPoint("BOTTOMRIGHT", scrollBG, "BOTTOMRIGHT", -4, 4)
scrollFrame:SetScript("OnEnter", OnEnter)
scrollFrame:SetScript("OnLeave", OnLeave)
scrollFrame:SetScript("OnMouseUp", OnMouseUp)
scrollFrame:SetScript("OnReceiveDrag", OnReceiveDrag)
scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
scrollFrame:HookScript("OnVerticalScroll", OnVerticalScroll)
local editBox = CreateFrame("EditBox", nil, scrollFrame)
editBox:SetAllPoints()
editBox:SetFontObject(ChatFontNormal)
editBox:SetMultiLine(true)
editBox:EnableMouse(true)
editBox:SetAutoFocus(false)
editBox:SetCountInvisibleLetters(false)
editBox:SetScript("OnCursorChanged", OnCursorChanged)
editBox:SetScript("OnEditFocusLost", OnEditFocusLost)
editBox:SetScript("OnEnter", OnEnter)
editBox:SetScript("OnEscapePressed", editBox.ClearFocus)
editBox:SetScript("OnLeave", OnLeave)
editBox:SetScript("OnMouseDown", OnReceiveDrag)
editBox:SetScript("OnReceiveDrag", OnReceiveDrag)
editBox:SetScript("OnTextChanged", OnTextChanged)
editBox:SetScript("OnTextSet", OnTextSet)
scrollFrame:SetScrollChild(editBox)
local widget = {
button = button,
editBox = editBox,
frame = frame,
label = label,
labelHeight = 10,
numlines = 4,
scrollBar = scrollBar,
scrollBG = scrollBG,
scrollFrame = scrollFrame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
button.obj, editBox.obj, scrollFrame.obj = widget, widget, widget
return AceGUI:RegisterAsWidget(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)

View File

@@ -0,0 +1,281 @@
--[[-----------------------------------------------------------------------------
Slider Widget
Graphical Slider, like, for Range values.
-------------------------------------------------------------------------------]]
local Type, Version = "Slider", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs
local min, max, floor = math.min, math.max, math.floor
local tonumber, pairs = tonumber, pairs
-- WoW APIs
local PlaySound = PlaySound
local CreateFrame, UIParent = CreateFrame, UIParent
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GameFontHighlightSmall
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function UpdateText(self)
local value = self.value or 0
if self.ispercent then
self.editbox:SetText(("%s%%"):format(floor(value * 1000 + 0.5) / 10))
else
self.editbox:SetText(floor(value * 100 + 0.5) / 100)
end
end
local function UpdateLabels(self)
local min, max = (self.min or 0), (self.max or 100)
if self.ispercent then
self.lowtext:SetFormattedText("%s%%", (min * 100))
self.hightext:SetFormattedText("%s%%", (max * 100))
else
self.lowtext:SetText(min)
self.hightext:SetText(max)
end
end
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function Control_OnEnter(frame)
frame.obj:Fire("OnEnter")
end
local function Control_OnLeave(frame)
frame.obj:Fire("OnLeave")
end
local function Frame_OnMouseDown(frame)
frame.obj.slider:EnableMouseWheel(true)
AceGUI:ClearFocus()
end
local function Slider_OnValueChanged(frame)
local self = frame.obj
if not frame.setup then
local newvalue = frame:GetValue()
if newvalue ~= self.value and not self.disabled then
self.value = newvalue
self:Fire("OnValueChanged", newvalue)
end
if self.value then
UpdateText(self)
end
end
end
local function Slider_OnMouseUp(frame)
local self = frame.obj
self:Fire("OnMouseUp", self.value)
end
local function Slider_OnMouseWheel(frame, v)
local self = frame.obj
if not self.disabled then
local value = self.value
if v > 0 then
value = min(value + (self.step or 1), self.max)
else
value = max(value - (self.step or 1), self.min)
end
self.slider:SetValue(value)
end
end
local function EditBox_OnEscapePressed(frame)
frame:ClearFocus()
end
local function EditBox_OnEnterPressed(frame)
local self = frame.obj
local value = frame:GetText()
if self.ispercent then
value = value:gsub('%%', '')
value = tonumber(value) / 100
else
value = tonumber(value)
end
if value then
PlaySound("igMainMenuOptionCheckBoxOn")
self.slider:SetValue(value)
self:Fire("OnMouseUp", value)
end
end
local function EditBox_OnEnter(frame)
frame:SetBackdropBorderColor(0.5, 0.5, 0.5, 1)
end
local function EditBox_OnLeave(frame)
frame:SetBackdropBorderColor(0.3, 0.3, 0.3, 0.8)
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
self:SetWidth(200)
self:SetHeight(44)
self:SetDisabled(false)
self:SetIsPercent(nil)
self:SetSliderValues(0,100,1)
self:SetValue(0)
self.slider:EnableMouseWheel(false)
end,
-- ["OnRelease"] = nil,
["SetDisabled"] = function(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,
["SetValue"] = function(self, value)
self.slider.setup = true
self.slider:SetValue(value)
self.value = value
UpdateText(self)
self.slider.setup = nil
end,
["GetValue"] = function(self)
return self.value
end,
["SetLabel"] = function(self, text)
self.label:SetText(text)
end,
["SetSliderValues"] = function(self, min, max, step)
local frame = self.slider
frame.setup = true
self.min = min
self.max = max
self.step = step
frame:SetMinMaxValues(min or 0,max or 100)
UpdateLabels(self)
frame:SetValueStep(step or 1)
if self.value then
frame:SetValue(self.value)
end
frame.setup = nil
end,
["SetIsPercent"] = function(self, value)
self.ispercent = value
UpdateLabels(self)
UpdateText(self)
end
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local SliderBackdrop = {
bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
tile = true, tileSize = 8, edgeSize = 8,
insets = { left = 3, right = 3, top = 6, bottom = 6 }
}
local ManualBackdrop = {
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
tile = true, edgeSize = 1, tileSize = 5,
}
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
frame:EnableMouse(true)
frame:SetScript("OnMouseDown", Frame_OnMouseDown)
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
label:SetPoint("TOPLEFT")
label:SetPoint("TOPRIGHT")
label:SetJustifyH("CENTER")
label:SetHeight(15)
local slider = CreateFrame("Slider", nil, frame)
slider:SetOrientation("HORIZONTAL")
slider:SetHeight(15)
slider:SetHitRectInsets(0, 0, -10, 0)
slider:SetBackdrop(SliderBackdrop)
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Horizontal")
slider:SetPoint("TOP", label, "BOTTOM")
slider:SetPoint("LEFT", 3, 0)
slider:SetPoint("RIGHT", -3, 0)
slider:SetValue(0)
slider:SetScript("OnValueChanged",Slider_OnValueChanged)
slider:SetScript("OnEnter", Control_OnEnter)
slider:SetScript("OnLeave", Control_OnLeave)
slider:SetScript("OnMouseUp", Slider_OnMouseUp)
slider:SetScript("OnMouseWheel", Slider_OnMouseWheel)
local lowtext = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
lowtext:SetPoint("TOPLEFT", slider, "BOTTOMLEFT", 2, 3)
local hightext = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
hightext:SetPoint("TOPRIGHT", slider, "BOTTOMRIGHT", -2, 3)
local editbox = CreateFrame("EditBox", nil, frame)
editbox:SetAutoFocus(false)
editbox:SetFontObject(GameFontHighlightSmall)
editbox:SetPoint("TOP", slider, "BOTTOM")
editbox:SetHeight(14)
editbox:SetWidth(70)
editbox:SetJustifyH("CENTER")
editbox:EnableMouse(true)
editbox:SetBackdrop(ManualBackdrop)
editbox:SetBackdropColor(0, 0, 0, 0.5)
editbox:SetBackdropBorderColor(0.3, 0.3, 0.30, 0.80)
editbox:SetScript("OnEnter", EditBox_OnEnter)
editbox:SetScript("OnLeave", EditBox_OnLeave)
editbox:SetScript("OnEnterPressed", EditBox_OnEnterPressed)
editbox:SetScript("OnEscapePressed", EditBox_OnEscapePressed)
local widget = {
label = label,
slider = slider,
lowtext = lowtext,
hightext = hightext,
editbox = editbox,
alignoffset = 25,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
slider.obj, editbox.obj = widget, widget
return AceGUI:RegisterAsWidget(widget)
end
AceGUI:RegisterWidgetType(Type,Constructor,Version)

View File

@@ -0,0 +1,240 @@
--[[ $Id: CallbackHandler-1.0.lua 965 2010-08-09 00:47:52Z mikk $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 6
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
if not CallbackHandler then return end -- No upgrade needed
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
-- Lua APIs
local tconcat = table.concat
local assert, error, loadstring = assert, error, loadstring
local setmetatable, rawset, rawget = setmetatable, rawset, rawget
local next, select, pairs, type, tostring = next, select, pairs, type, tostring
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: geterrorhandler
local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local next, xpcall, eh = ...
local method, ARGS
local function call() method(ARGS) end
local function dispatch(handlers, ...)
local index
index, method = next(handlers)
if not method then return end
local OLD_ARGS = ARGS
ARGS = ...
repeat
xpcall(call, eh)
index, method = next(handlers, index)
until not method
ARGS = OLD_ARGS
end
return dispatch
]]
local ARGS, OLD_ARGS = {}, {}
for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
--------------------------------------------------------------------------
-- CallbackHandler:New
--
-- target - target object to embed public APIs in
-- RegisterName - name of the callback registration API, default "RegisterCallback"
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
-- TODO: Remove this after beta has gone out
assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
RegisterName = RegisterName or "RegisterCallback"
UnregisterName = UnregisterName or "UnregisterCallback"
if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
UnregisterAllName = "UnregisterAllCallbacks"
end
-- we declare all objects and exported APIs inside this closure to quickly gain access
-- to e.g. function names, the "target" parameter, etc
-- Create the registry object
local events = setmetatable({}, meta)
local registry = { recurse=0, events=events }
-- registry:Fire() - fires the given event/message into the registry
function registry:Fire(eventname, ...)
if not rawget(events, eventname) or not next(events[eventname]) then return end
local oldrecurse = registry.recurse
registry.recurse = oldrecurse + 1
Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
registry.recurse = oldrecurse
if registry.insertQueue and oldrecurse==0 then
-- Something in one of our callbacks wanted to register more callbacks; they got queued
for eventname,callbacks in pairs(registry.insertQueue) do
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
for self,func in pairs(callbacks) do
events[eventname][self] = func
-- fire OnUsed callback?
if first and registry.OnUsed then
registry.OnUsed(registry, target, eventname)
first = nil
end
end
end
registry.insertQueue = nil
end
end
-- Registration of a callback, handles:
-- self["method"], leads to self["method"](self, ...)
-- self with function ref, leads to functionref(...)
-- "addonId" (instead of self) with function ref, leads to functionref(...)
-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
if type(eventname) ~= "string" then
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
end
method = method or eventname
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
if type(method) ~= "string" and type(method) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
end
local regfunc
if type(method) == "string" then
-- self["method"] calling style
if type(self) ~= "table" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
elseif self==target then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
elseif type(self[method]) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
end
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) self[method](self,arg,...) end
else
regfunc = function(...) self[method](self,...) end
end
else
-- function ref with self=object or self="addonId" or self=thread
if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread 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.

View 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>

26
MogIt/Libs/Embeds.xml Normal file
View File

@@ -0,0 +1,26 @@
<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="LibStub\LibStub.lua"/>
<Include file="CallbackHandler-1.0\CallbackHandler-1.0.xml"/>
<Include file="AceGUI-3.0\AceGUI-3.0.xml"/>
<Include file="AceConfig-3.0\AceConfig-3.0.xml"/>
<Include file="AceDB-3.0\AceDB-3.0.xml"/>
<Include file="AceDBOptions-3.0\AceDBOptions-3.0.xml"/>
<Include file="LibAddonInfo-1.0\lib.xml"/>
<Script file="LibDataBroker-1.1\LibDataBroker-1.1.lua"/>
<Script file="LibDBIcon-1.0\LibDBIcon-1.0.lua"/>
<Include file="LibBabble-Boss-3.0\lib.xml"/>
<Include file="LibBabble-Inventory-3.0\lib.xml"/>
<Include file="LibBabble-Race-3.0\lib.xml"/>
<Include file="Libra\Libra.xml"/>
<Script file="LibItemInfo-1.0\LibItemInfo-1.0.lua"/>
</Ui>

View File

@@ -0,0 +1,219 @@
local lib,old = LibStub:NewLibrary("LibAddonInfo-1.0",1);
if not lib then return end
local L = {};
local locale = GetLocale();
-- frFR
if locale == "frFR" then
L["About"] = "à propos de";
L["Click and press Ctrl-C to copy"] = "Click and press Ctrl-C to copy";
-- deDE
elseif locale == "deDE" then
L["About"] = "Über";
L["Click and press Ctrl-C to copy"] = "Klicken und Strg-C drücken zum kopieren";
-- esES
elseif locale == "esES" then
L["About"] = "Acerca de";
L["Click and press Ctrl-C to copy"] = "Click and press Ctrl-C to copy";
-- esMX
elseif locale == "esMX" then
L["About"] = "Sobre";
L["Click and press Ctrl-C to copy"] = "Click and press Ctrl-C to copy";
-- koKR
elseif locale == "koKR" then
L["About"] = "대하여";
L["Click and press Ctrl-C to copy"] = "클릭 후 Ctrl-C 복사";
-- ruRU
elseif locale == "ruRU" then
L["About"] = "Об аддоне";
L["Click and press Ctrl-C to copy"] = "Click and press Ctrl-C to copy";
-- zhCN
elseif locale == "zhCN" then
L["About"] = "关于";
L["Click and press Ctrl-C to copy"] = "点击并 Ctrl-C 复制";
-- zhTW
elseif locale == "zhTW" then
L["About"] = "關於";
L["Click and press Ctrl-C to copy"] = "左鍵點擊並按下 Ctrl-C 以複製字串";
-- enUS and non-localized
else
L["About"] ="About";
L["Click and press Ctrl-C to copy"] = "Click and press Ctrl-C to copy";
end
function lib:CreateFrame(addon,parent,path)
local frame = CreateFrame("Frame",nil,UIParent);
frame:Hide();
frame.addon = addon:gsub(" ","");
frame.name = parent and L["About"] or frame.addon;
frame.parent = parent;
frame.path = path;
InterfaceOptions_AddCategory(frame);
lib:CreateLayout(frame);
return frame;
end
local editbox = CreateFrame('EditBox',nil,UIParent);
editbox:Hide();
editbox:SetAutoFocus(true);
editbox:SetHeight(32);
editbox:SetFontObject('GameFontHighlightSmall');
local left = editbox:CreateTexture(nil,"BACKGROUND");
left:SetSize(8,20);
left:SetPoint("LEFT",-5,0);
left:SetTexture("Interface\\Common\\Common-Input-Border");
left:SetTexCoord(0,0.0625,0,0.625);
local right = editbox:CreateTexture(nil,"BACKGROUND");
right:SetSize(8,20);
right:SetPoint("RIGHT",0,0);
right:SetTexture("Interface\\Common\\Common-Input-Border");
right:SetTexCoord(0.9375,1,0,0.625);
local center = editbox:CreateTexture(nil,"BACKGROUND");
center:SetHeight(20);
center:SetPoint("RIGHT",right,"LEFT",0,0);
center:SetPoint("LEFT",left,"RIGHT",0,0);
center:SetTexture("Interface\\Common\\Common-Input-Border");
center:SetTexCoord(0.0625,0.9375,0,0.625);
editbox:SetScript("OnEscapePressed",editbox.ClearFocus);
editbox:SetScript("OnEnterPressed",editbox.ClearFocus);
editbox:SetScript("OnEditFocusLost",editbox.Hide);
editbox:SetScript("OnEditFocusGained",editbox.HighlightText);
editbox:SetScript("OnTextChanged",function(self)
self:SetText(self:GetParent().value);
self:HighlightText();
end);
local function EditBoxEnter(self)
GameTooltip:SetOwner(self,"ANCHOR_TOPRIGHT");
GameTooltip:SetText(L["Click and press Ctrl-C to copy"]);
end
local function EditBoxLeave()
GameTooltip:Hide();
end
local function EditBoxShow(self)
editbox:SetText(self.value);
editbox:SetParent(self);
editbox:SetPoint("LEFT",self);
editbox:SetPoint("RIGHT",self);
editbox:Show();
end
local fields = {"Version", "Author", "X-Category", "X-License", "X-Email", "Email", "eMail", "X-Website", "X-Credits", "X-Localizations", "X-Donate"};
local haseditbox = {["X-Website"] = true, ["X-Email"] = true, ["Email"] = true, ["eMail"] = true, ["X-Donate"] = true};
local path;
local flags = {
["enus"] = "English",
["frfr"] = "French",
["dede"] = "German",
["eses"] = "Spanish",
["esmx"] = "Latin American Spanish",
["ruru"] = "Russian",
["kokr"] = "Korean",
["zhcn"] = "Simplified Chinese",
["zhtw"] = "Traditional Chinese",
["ptbr"] = "Brazilian Portuguese",
["itit"] = "Italian",
};
local function FormatLocale(newline,str)
local output;
local flag = str:lower();
if flags[flag] then
if path then
output = "|T"..path.."\\"..flag..":16|t ";
else
output = "";
end
output = output..flags[flag];
end
return (newline > "" and "\n" or "")..(output or str);
end
function lib:CreateLayout(frame)
frame.title = frame:CreateFontString(nil,"ARTWORK","GameFontNormalLarge");
frame.title:SetPoint("TOPLEFT",16,-16)
frame.title:SetText(frame.name);
local notes = "Notes";
if (locale ~= "enUS") then
notes = notes.."-"..locale;
end
notes = GetAddOnMetadata(frame.addon,notes) or GetAddOnMetadata(frame.addon,"Notes");
frame.notes = frame:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
frame.notes:SetHeight(32);
frame.notes:SetPoint("TOPLEFT",frame.title,"BOTTOMLEFT",0,-8);
frame.notes:SetPoint("RIGHT",frame,-32,0);
frame.notes:SetNonSpaceWrap(true);
frame.notes:SetJustifyH("LEFT");
frame.notes:SetJustifyV("TOP");
frame.notes:SetText(notes or "");
frame.label = {};
frame.info = {};
local anchor;
for _,field in ipairs(fields) do
local value = GetAddOnMetadata(frame.addon,field);
if value then
frame.label[field] = frame:CreateFontString(nil,"ARTWORK","GameFontNormalSmall");
frame.label[field]:SetWidth(75);
frame.label[field]:SetJustifyH("RIGHT");
frame.label[field]:SetText(field:gsub("X%-",""));
if not anchor then
frame.label[field]:SetPoint("TOPLEFT",frame.notes,"BOTTOMLEFT",-2,-12);
else
frame.label[field]:SetPoint("TOPRIGHT",anchor,"BOTTOMLEFT",-4,-10);
end
frame.info[field] = frame:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall");
frame.info[field]:SetPoint("TOPLEFT",frame.label[field],"TOPRIGHT",4,0);
frame.info[field]:SetPoint("RIGHT",frame,-16,0);
frame.info[field]:SetJustifyH("LEFT");
frame.info[field]:SetJustifyV("TOP");
frame.info[field]:SetNonSpaceWrap(true);
value = value:gsub("^%s*","");
value = value:gsub("%s*$","");
if field == "Author" then
value = value:gsub("%s*[,&]%s*","\n");
elseif field == "Version" then
value = value:gsub("@project.revision@","Repository");
elseif field == "X-Localizations" then
path = frame.path;
value = value:gsub("(,?)%s*([^,]+)%s*",FormatLocale);
--value = value:gsub("%s*[,]%s*","\n");
end
value = (haseditbox[field] and "|cff9999ff" or "")..value;
frame.info[field]:SetText(value);
if haseditbox[field] then
local button = CreateFrame("Button",nil,frame);
button:SetAllPoints(frame.info[field]);
button.value = value;
button:SetScript("OnClick",EditBoxShow);
button:SetScript("OnEnter",EditBoxEnter);
button:SetScript("OnLeave",EditBoxLeave);
end
anchor = frame.info[field];
end
end
end
-- make work for 2nd pass layout
-- make work for frame as input in create
-- custom fields
-- function/str for fields and/or editboxes

View 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="LibAddonInfo-1.0.lua" />
</Ui>

View File

@@ -0,0 +1,38 @@
------------------------------------------------------------------------
r305 | nevcairiel | 2010-10-10 12:18:04 +0000 (Sun, 10 Oct 2010) | 1 line
Changed paths:
A /tags/3.3-release42 (from /trunk:304)
Weekly Tag - #42
------------------------------------------------------------------------
r304 | nevcairiel | 2010-10-10 12:17:44 +0000 (Sun, 10 Oct 2010) | 1 line
Changed paths:
M /trunk/LibBabble-Boss-3.0.lua
Automated LibBabble re-generation from the localization system
------------------------------------------------------------------------
r302 | nevcairiel | 2010-09-18 12:45:36 +0000 (Sat, 18 Sep 2010) | 1 line
Changed paths:
M /trunk/LibBabble-Boss-3.0.lua
Automated LibBabble re-generation from the localization system
------------------------------------------------------------------------
r301 | nevcairiel | 2010-09-12 12:37:10 +0000 (Sun, 12 Sep 2010) | 1 line
Changed paths:
M /trunk/LibBabble-Boss-3.0.lua
Automated LibBabble re-generation from the localization system
------------------------------------------------------------------------
r300 | nevcairiel | 2010-09-12 12:29:18 +0000 (Sun, 12 Sep 2010) | 1 line
Changed paths:
M /trunk/.pkgmeta
D /trunk/LibStub
Remove hard-embeded LibStub
------------------------------------------------------------------------
r298 | nevcairiel | 2010-09-10 17:22:40 +0000 (Fri, 10 Sep 2010) | 1 line
Changed paths:
M /trunk/LibBabble-Boss-3.0.lua
Automated LibBabble re-generation from the localization system
------------------------------------------------------------------------

View File

@@ -0,0 +1,292 @@
-- LibBabble-3.0 is hereby placed in the Public Domain
-- Credits: ckknight
local LIBBABBLE_MAJOR, LIBBABBLE_MINOR = "LibBabble-3.0", 2
local LibBabble = LibStub:NewLibrary(LIBBABBLE_MAJOR, LIBBABBLE_MINOR)
if not LibBabble then
return
end
local data = LibBabble.data or {}
for k,v in pairs(LibBabble) do
LibBabble[k] = nil
end
LibBabble.data = data
local tablesToDB = {}
for namespace, db in pairs(data) do
for k,v in pairs(db) do
tablesToDB[v] = db
end
end
local function warn(message)
local _, ret = pcall(error, message, 3)
geterrorhandler()(ret)
end
local lookup_mt = { __index = function(self, key)
local db = tablesToDB[self]
local current_key = db.current[key]
if current_key then
self[key] = current_key
return current_key
end
local base_key = db.base[key]
local real_MAJOR_VERSION
for k,v in pairs(data) do
if v == db then
real_MAJOR_VERSION = k
break
end
end
if not real_MAJOR_VERSION then
real_MAJOR_VERSION = LIBBABBLE_MAJOR
end
if base_key then
warn(("%s: Translation %q not found for locale %q"):format(real_MAJOR_VERSION, key, GetLocale()))
rawset(self, key, base_key)
return base_key
end
warn(("%s: Translation %q not found."):format(real_MAJOR_VERSION, key))
rawset(self, key, key)
return key
end }
local function initLookup(module, lookup)
local db = tablesToDB[module]
for k in pairs(lookup) do
lookup[k] = nil
end
setmetatable(lookup, lookup_mt)
tablesToDB[lookup] = db
db.lookup = lookup
return lookup
end
local function initReverse(module, reverse)
local db = tablesToDB[module]
for k in pairs(reverse) do
reverse[k] = nil
end
for k,v in pairs(db.current) do
reverse[v] = k
end
tablesToDB[reverse] = db
db.reverse = reverse
db.reverseIterators = nil
return reverse
end
local prototype = {}
local prototype_mt = {__index = prototype}
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will warn but allow the code to pass through.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local BL = B:GetLookupTable()
assert(BL["Some english word"] == "Some localized word")
DoSomething(BL["Some english word that doesn't exist"]) -- warning!
-----------------------------------------------------------------------------]]
function prototype:GetLookupTable()
local db = tablesToDB[self]
local lookup = db.lookup
if lookup then
return lookup
end
return initLookup(self, {})
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local B_has = B:GetUnstrictLookupTable()
assert(B_has["Some english word"] == "Some localized word")
assert(B_has["Some english word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetUnstrictLookupTable()
local db = tablesToDB[self]
return db.current
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
* This is useful for checking if the base (English) table has a key, even if the localized one does not have it registered.
Returns:
A lookup table for english to localized words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local B_hasBase = B:GetBaseLookupTable()
assert(B_hasBase["Some english word"] == "Some english word")
assert(B_hasBase["Some english word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetBaseLookupTable()
local db = tablesToDB[self]
return db.base
end
--[[---------------------------------------------------------------------------
Notes:
* If you try to access a nonexistent key, it will return nil.
* This will return only one English word that it maps to, if there are more than one to check, see :GetReverseIterator("word")
Returns:
A lookup table for localized to english words.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
local BR = B:GetReverseLookupTable()
assert(BR["Some localized word"] == "Some english word")
assert(BR["Some localized word that doesn't exist"] == nil)
-----------------------------------------------------------------------------]]
function prototype:GetReverseLookupTable()
local db = tablesToDB[self]
local reverse = db.reverse
if reverse then
return reverse
end
return initReverse(self, {})
end
local blank = {}
local weakVal = {__mode='v'}
--[[---------------------------------------------------------------------------
Arguments:
string - the localized word to chek for.
Returns:
An iterator to traverse all English words that map to the given key
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
for word in B:GetReverseIterator("Some localized word") do
DoSomething(word)
end
-----------------------------------------------------------------------------]]
function prototype:GetReverseIterator(key)
local db = tablesToDB[self]
local reverseIterators = db.reverseIterators
if not reverseIterators then
reverseIterators = setmetatable({}, weakVal)
db.reverseIterators = reverseIterators
elseif reverseIterators[key] then
return pairs(reverseIterators[key])
end
local t
for k,v in pairs(db.current) do
if v == key then
if not t then
t = {}
end
t[k] = true
end
end
reverseIterators[key] = t or blank
return pairs(reverseIterators[key])
end
--[[---------------------------------------------------------------------------
Returns:
An iterator to traverse all translations English to localized.
Example:
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
for english, localized in B:Iterate() do
DoSomething(english, localized)
end
-----------------------------------------------------------------------------]]
function prototype:Iterate()
local db = tablesToDB[self]
return pairs(db.current)
end
-- #NODOC
-- modules need to call this to set the base table
function prototype:SetBaseTranslations(base)
local db = tablesToDB[self]
local oldBase = db.base
if oldBase then
for k in pairs(oldBase) do
oldBase[k] = nil
end
for k, v in pairs(base) do
oldBase[k] = v
end
base = oldBase
else
db.base = base
end
for k,v in pairs(base) do
if v == true then
base[k] = k
end
end
end
local function init(module)
local db = tablesToDB[module]
if db.lookup then
initLookup(module, db.lookup)
end
if db.reverse then
initReverse(module, db.reverse)
end
db.reverseIterators = nil
end
-- #NODOC
-- modules need to call this to set the current table. if current is true, use the base table.
function prototype:SetCurrentTranslations(current)
local db = tablesToDB[self]
if current == true then
db.current = db.base
else
local oldCurrent = db.current
if oldCurrent then
for k in pairs(oldCurrent) do
oldCurrent[k] = nil
end
for k, v in pairs(current) do
oldCurrent[k] = v
end
current = oldCurrent
else
db.current = current
end
end
init(self)
end
for namespace, db in pairs(data) do
setmetatable(db.module, prototype_mt)
init(db.module)
end
-- #NODOC
-- modules need to call this to create a new namespace.
function LibBabble:New(namespace, minor)
local module, oldminor = LibStub:NewLibrary(namespace, minor)
if not module then
return
end
if not oldminor then
local db = {
module = module,
}
data[namespace] = db
tablesToDB[module] = db
else
for k,v in pairs(module) do
module[k] = nil
end
end
setmetatable(module, prototype_mt)
return module
end

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More