/
<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="LanguageCycle.lua"/> |
<Frame name="Language_Cycle_Panel" parent="UIParent" enableMouse="true" toplevel="true" movable="true" frameStrata="HIGH"> |
<Size> |
<AbsDimension x="151" y="56"/> |
</Size> |
<Anchors> |
<Anchor point="TOP" relativePoint="TOP"> |
<Offset> |
<AbsDimension x="0" y="0"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLoad function="Language_Cycle_OnLoad" /> |
<OnEvent function="Language_Cycle_OnEvent" /> |
<OnUpdate function="Language_Cycle_OnUpdate" /> |
<OnDragStart> |
self:StartMoving(); |
</OnDragStart> |
<OnDragStop> |
self:StopMovingOrSizing(); |
ValidateFramePosition(this); |
</OnDragStop> |
<OnEnter function="Language_Cycle_Backdrop_Show" /> |
<OnLeave function="Language_Cycle_Backdrop_Hide" /> |
</Scripts> |
<Frames> |
<Frame name="Language_Cycle_Panel_Backdrop" parent="Language_Cycle_Panel" visible="false"> |
<Backdrop name="$parentBackdrop" bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true"> |
<EdgeSize> |
<AbsValue val="16"/> |
</EdgeSize> |
<TileSize> |
<AbsValue val="16"/> |
</TileSize> |
<BackgroundInsets> |
<AbsInset left="5" right="5" top="5" bottom="5"/> |
</BackgroundInsets> |
</Backdrop> |
<Size> |
<AbsDimension x="151" y="56"/> |
</Size> |
<Anchors> |
<Anchor point="TOP" relativePoint="TOP"> |
</Anchor> |
</Anchors> |
<Frames> |
<Button name="Language_Cycle_CloseButton" parent="Language_Cycle_Panel_Backdrop"> |
<Size> |
<AbsDimension x="34" y="34"/> |
</Size> |
<Anchors> |
<Anchor point="TOPRIGHT"> |
<Offset> |
<AbsDimension x="3" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnEnter function="Language_Cycle_Backdrop_Show" /> |
<OnLeave function="Language_Cycle_Backdrop_Hide" /> |
<OnClick> |
PlaySound("igMainMenuOptionCheckBoxOff"); |
Language_Cycle_Panel_Visible(); |
</OnClick> |
</Scripts> |
<NormalTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Up"/> |
<PushedTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Down"/> |
<HighlightTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Highlight" alphaMode="ADD"/> |
</Button> |
<CheckButton name="Language_Cycle_Party_Toggle" inherits="UICheckButtonTemplate"> |
<Size> |
<AbsDimension x="28" y="28"/> |
</Size> |
<Anchors> |
<Anchor point="TOPRIGHT" relativePoint="RIGHT"> |
<Offset> |
<AbsDimension x="-4" y="3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnEnter function="Language_Cycle_Backdrop_Show" /> |
<OnLeave function="Language_Cycle_Backdrop_Hide" /> |
<OnClick> |
if ( self:GetChecked() ) then |
PlaySound("igMainMenuOptionCheckBoxOff"); |
else |
PlaySound("igMainMenuOptionCheckBoxOn"); |
end |
Language_Cycle_Toggle_Group(); |
</OnClick> |
</Scripts> |
</CheckButton> |
</Frames> |
<Layers> |
<Layer level="OVERLAY"> |
<FontString name="Language_Cycle_Party_Toggle_Text" inherits="GameFontNormalSmall" text="Speak Common in Party/Guild chat:"> |
<Size> |
<AbsDimension x="110" y="42"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="0" y="-15"/> |
</Offset> |
</Anchor> |
</Anchors> |
</FontString> |
</Layer> |
</Layers> |
</Frame> |
<!-- Button for Language Cycling --> |
<Button name="Language_Cycle_Button" inherits="UIPanelButtonTemplate" enableMouse="true" visible="true" text="Loading..."> |
<Size> |
<AbsDimension x="125" y="21"/> |
</Size> |
<Anchors> |
<Anchor point="TOPLEFT" relativePoint="TOPLEFT"> |
<Offset> |
<AbsDimension x="3" y="-3"/> |
</Offset> |
</Anchor> |
</Anchors> |
<Scripts> |
<OnLoad> |
self:RegisterForClicks("LeftButtonDown", "RightButtonDown") |
</OnLoad> |
<OnClick> |
if (IsAltKeyDown()) then |
Language_Cycle_Clear(); |
PlaySound("igMainMenuOptionCheckBoxOff"); |
else |
Language_Cycle_Language_Clicked(button); |
PlaySound("igMainMenuOptionCheckBoxOn"); |
end |
</OnClick> |
<OnEnter function="Language_Cycle_Backdrop_Show" /> |
<OnLeave function="Language_Cycle_Backdrop_Hide" /> |
</Scripts> |
</Button> |
</Frames> |
</Frame> |
</Ui> |
-- Language cycle script |
-- Version 5.0.4.a |
local ButtonTexture = "Interface\\Addons\\LanguageCycle\\media\\LanguageCycleIcon" |
local addonName = "LanguageCycle" |
BINDING_HEADER_LANGUAGECYCLE="Language Cycle"; |
local defaults = { |
saved_language = {}; |
translate_group = true; |
panel_visible = true; |
panel_locked = false; |
minimapIcon = { |
hide = false, |
minimapPos = 220, |
radius = 80, |
} |
} |
if not LANGUAGE_CYCLE then |
LANGUAGE_CYCLE = defaults |
else |
for k, v in pairs(defaults) do |
if LANGUAGE_CYCLE[k] == nil or type(LANGUAGE_CYCLE[k]) ~= type(v) then |
LANGUAGE_CYCLE[k] = v |
end |
end |
end |
LC_default_language = ""; |
LC_verbose = true; |
LC_unknown = "Unknown Entity"; |
LC_realm_name = ""; |
LC_player_name = ""; |
LC_player_id = nil; |
LC_panel_height = 0; |
LC_panel_width = 0; |
LC_version = "4.2.2, by Halya, Argent Dawn, EU"; |
LC_Help_Text={}; |
LC_Help_Text[0]="Language Cycle will respond to the following commands:"; |
LC_Help_Text[1]="- /lc : Toggles spoken language between racial/common"; |
LC_Help_Text[2]="- /lc status : Displays current settings"; |
LC_Help_Text[3]="- /lc toggle : Toggles Guild/Party translation on/off"; |
LC_Help_Text[4]="- /lc help : Displays this message"; |
LC_Help_Text[5]="- /lc show : Display the language cycle button"; |
LC_Help_Text[6]="- /lc hide : Hide the language cycle button"; |
LC_Help_Text[7]="- /lc MM : Toggle the language cycle mini-map button"; |
LC_Help_Text[8]="--------------------------------------------------------------"; |
--Save Blizzard's original SendText function |
local LC_Blizzard_SendChatMessage; |
local LCButtonFrameObject = LibStub:GetLibrary("LibDataBroker-1.1"):NewDataObject(addonName, { |
type = "data source", |
text = LANGUAGE_CYCLE.minimapIcon.text, |
icon = ButtonTexture, |
OnClick = function(frame, button) |
GameTooltip:Hide() |
if button =="LeftButton" then |
Language_Cycle_Cycle(); |
elseif button =="MiddleButton" then |
local t = 0; |
while LC_Help_Text[t] ~= nil do |
DEFAULT_CHAT_FRAME:AddMessage(LC_Help_Text[t],0.0, 1.0, 0.0); |
t = t + 1; |
end |
elseif button == "RightButton" then |
Language_Cycle_Panel_Visible(); |
end |
end, |
OnTooltipShow = function(tooltip) |
if tooltip and tooltip.AddLine then |
tooltip:SetText("LanguageCycle") |
tooltip:AddLine("Left-Click: Cycle Language|nRight-Click: Show/Hide Built-in Panel|nMiddle-Click: Show Help",.8,.8,.8,1) |
tooltip:Show() |
end |
end, |
}) |
function Language_Cycle_OnLoad( self ) |
-- Hook SendChatMessage |
LC_Blizzard_SendChatMessage = SendChatMessage; |
SendChatMessage = LC_SendChatMessage; |
SlashCmdList["LANGUAGECYCLE"] = Language_Cycle_Slash; |
SLASH_LANGUAGECYCLE1 = "/lc"; |
ShowUIPanel(Language_Cycle_Panel); |
if ( not Language_Cycle_Panel:IsVisible() ) then |
Language_Cycle_Panel:SetOwner(UIParent, "ANCHOR_PRESERVE"); |
end |
Language_Cycle_Panel_Backdrop:SetBackdropBorderColor(1,1,1); |
Language_Cycle_Panel_Backdrop:SetBackdropColor(0.3, 0.3, 0.3); |
Language_Cycle_Backdrop_Hide(); |
LC_panel_height = Language_Cycle_Panel:GetHeight(); |
LC_panel_width = Language_Cycle_Panel:GetWidth(); |
Language_Cycle_Party_Toggle_Text:SetJustifyH("Right"); |
Language_Cycle_Add_Message("LanguageCycle loaded; Type '/lc help' for a list of options; Version " .. LC_version); |
-- self:SetPadding(16); |
self:RegisterForDrag("LeftButton"); |
self:RegisterEvent("VARIABLES_LOADED"); |
self:RegisterEvent("PLAYER_ENTERING_WORLD"); |
end |
function Language_Cycle_Get_Version() |
return LC_version |
end |
-- replace Blizzard's SendChatMessage function instead. -Nhani |
function LC_SendChatMessage(msg, chatType, language, channel) |
if (LC_player_id ~= nil) then |
language = LANGUAGE_CYCLE.saved_language[LC_player_id]; |
end |
-- Small change here. Instead of defining what channels we WANT |
-- in a common language, we define what channels we DON'T want. |
-- Since those are far fewer in number. -Nhani |
if (LANGUAGE_CYCLE.translate_group) then |
if (chatType ~= "SAY" and chatType ~= "YELL") then |
if (language ~= LC_default_language) then |
language = LC_default_language; |
end |
end |
end |
local numLanguages = GetNumLanguages(); |
local i; |
for i = 1, numLanguages, 1 do |
local getlanguage, getlanguageID = GetLanguageByIndex(i); |
if (language == getlanguage) then |
languageID = getlanguageID; |
end |
end |
LC_Blizzard_SendChatMessage(msg, chatType, languageID, channel); |
end |
function Language_Cycle_Panel_Visible() |
if (Language_Cycle_Panel:IsVisible() ) then |
HideUIPanel(Language_Cycle_Panel); |
LANGUAGE_CYCLE.panel_visible = false; |
else |
ShowUIPanel(Language_Cycle_Panel); |
LANGUAGE_CYCLE.panel_visible = true; |
end |
end |
function Language_Cycle_Backdrop_Show(override) |
if (LANGUAGE_CYCLE.panel_locked and not override) then |
else |
Language_Cycle_Panel_Backdrop:Show(); |
end |
end |
function Language_Cycle_Backdrop_Hide(override) |
if (LANGUAGE_CYCLE.panel_locked and not override) then |
else |
Language_Cycle_Panel_Backdrop:Hide(); |
end |
end |
function Language_Cycle_Cycle() |
local numLangs = GetNumLanguages(); |
local currentlang = 0; |
local lang; |
lang = Language_Cycle_Get_Lang(); |
for i=1,numLangs,1 do |
if (lang == GetLanguageByIndex(i)) then |
currentlang = i; |
end |
end |
if (currentlang == numLangs) then |
currentlang = 1; |
else |
currentlang = currentlang + 1; |
end |
Language_Cycle_Set_Lang(GetLanguageByIndex(currentlang)); |
-- if (IsAddOnLoaded("Titan")) then |
-- TitanPanelButton_UpdateButton(TITAN_LANGUAGECYCLE_ID); |
-- end |
-- if (IsAddOnLoaded("FuBar")) then |
-- LanguageCycleFuBar:UpdateText() |
-- end |
-- For debugging |
-- Langauge_Cycle_Debug_Message(); |
end |
function Language_Cycle_Language_Clicked(button) |
if (button == "LeftButton") then |
LC_verbose = false; |
Language_Cycle_Cycle(); |
LC_verbose = true; |
end |
if (button == "RightButton") then |
LANGUAGE_CYCLE.panel_locked = not LANGUAGE_CYCLE.panel_locked; |
Langauge_Cycle_Lock_Backdrop(); |
end |
end |
function Langauge_Cycle_Lock_Backdrop() |
if (LANGUAGE_CYCLE.panel_locked) then |
Language_Cycle_Backdrop_Hide(true); |
Language_Cycle_Panel:SetHeight(Language_Cycle_Button:GetHeight()); |
Language_Cycle_Panel:SetWidth(Language_Cycle_Button:GetWidth()); |
else |
Language_Cycle_Backdrop_Show(true); |
Language_Cycle_Panel:SetHeight(LC_panel_height); |
Language_Cycle_Panel:SetWidth(LC_panel_width); |
end |
end |
function Language_Cycle_Variables_Loaded() |
--Called when variables_loaded event fires, usually on UI reload |
if (LANGUAGE_CYCLE.panel_visible) then |
ShowUIPanel(Language_Cycle_Panel); |
else |
HideUIPanel(Language_Cycle_Panel); |
end |
Langauge_Cycle_Lock_Backdrop(); |
-- For debugging |
-- Language_Cycle_Debug_Message(); |
-- Language_Cycle_Add_Message("Onload done"); |
end |
function Language_Cycle_OnEvent( self, event, ... ) |
if (event == "VARIABLES_LOADED") then |
Language_Cycle_Variables_Loaded(); |
-- Add LanguageCycle to myAddOns addons list |
if(myAddOnsFrame) then |
myAddOnsList.LanguageCycle = { |
name = "LanguageCycle", |
description = "A button to change your spoken language", |
version = Language_Cycle_Get_Version(), |
category = MYADDONS_CATEGORY_CHAT, |
frame = "Language_Cycle_Panel"}; |
end |
---------------------------------------------------------------------------------------- |
-- LDB Button Creation |
---------------------------------------------------------------------------------------- |
local defaults = { |
minimapIcon = { |
hide = false, |
minimapPos = 220, |
radius = 80, |
text = lang, |
} |
} |
if not LANGUAGE_CYCLE then |
LANGUAGE_CYCLE = defaults |
else |
for k, v in pairs(defaults) do |
if LANGUAGE_CYCLE[k] == nil or type(LANGUAGE_CYCLE[k]) ~= type(v) then |
LANGUAGE_CYCLE[k] = v |
end |
end |
end |
LibStub("LibDBIcon-1.0"):Register(addonName, LCButtonFrameObject, LANGUAGE_CYCLE.minimapIcon) |
end |
if (event == "PLAYER_ENTERING_WORLD") then |
Language_Cycle_Init(); |
end |
end |
function Language_Cycle_Init() |
--Called when the Player_Entering_World event fires, usually on character login. |
-- May be called later, if initialization fails |
LC_realm_name = string.gsub(GetCVar("realmName"),"'",""); |
LC_player_name = UnitName("player"); |
LC_default_language = GetDefaultLanguage(); |
LC_verbose = false; |
Language_Cycle_Backdrop_Hide(true); |
Language_Cycle_Set_Text_Color(); |
local lang; |
if (LC_player_name == nil or LC_player_name == LC_unknown or LC_realm_name == nil) then |
else |
LC_player_id = LC_realm_name .. " " .. LC_player_name; |
end |
lang = Language_Cycle_Get_Lang(); |
if (lang == nil) then |
else |
Language_Cycle_Set_Lang(lang) |
end |
if (LC_default_language == nil) then |
else |
Language_Cycle_Party_Toggle_Text:SetText("Speak " .. LC_default_language .. " in Party/Guild chat:"); |
end |
Language_Cycle_Set_Party_Checkbutton(); |
LC_verbose = true; |
-- For debugging |
-- Language_Cycle_Debug_Message(); |
-- Language_Cycle_Add_Message("Entering World Done"); |
end |
function Language_Cycle_OnUpdate( self, elapsed ) |
if (not LC_player_id) then |
Language_Cycle_Init(); |
end |
end |
function Language_Cycle_Set_Lang(lang) |
-- Updates the button text, chat window and returns a chat window message |
Language_Cycle_Button:SetText(lang); |
DEFAULT_CHAT_FRAME.editBox.language = lang; |
LANGUAGE_CYCLE.minimapIcon.text = lang; |
LCButtonFrameObject.text = lang |
if (LC_verbose) then |
Language_Cycle_Add_Message(string.format("Now speaking %s", lang)); |
end |
Language_Cycle_Save_Lang(lang); |
end |
function Language_Cycle_Save_Lang(lang) |
if (LC_player_id == nil) then |
else |
LANGUAGE_CYCLE.saved_language[LC_player_id] = lang; |
end |
end |
function Language_Cycle_Get_Lang() |
local lang, langID; |
if (LC_player_id == nil) then |
else |
lang = DEFAULT_CHAT_FRAME.editBox.language; |
if (LANGUAGE_CYCLE.saved_language[LC_player_id] == nil) then |
if (lang == nil) then |
lang = LC_default_language; |
end |
else |
lang = LANGUAGE_CYCLE.saved_language[LC_player_id]; |
end |
end |
return lang |
end |
function Language_Cycle_Debug_Message() |
local lang; |
lang = LANGUAGE_CYCLE.saved_language[LC_player_id]; |
if (lang == nil) then |
lang = "unknown"; |
end |
if not(LC_player_name == nil) then |
message(LC_player_name .. " speaks " .. lang); |
else |
message("LC_player_name is nil"); |
end |
end |
function Language_Cycle_Toggle_Group(verbose) |
if (LANGUAGE_CYCLE.translate_group) then |
LANGUAGE_CYCLE.translate_group = false; |
if (verbose) then |
Language_Cycle_Add_Message("Guild/Party translation is now off."); |
end |
else |
LANGUAGE_CYCLE.translate_group = true; |
if (verbose) then |
Language_Cycle_Add_Message("Guild/Party translation is now on."); |
end |
end |
Language_Cycle_Set_Text_Color(); |
Language_Cycle_Set_Party_Checkbutton(); |
-- if (IsAddOnLoaded("Titan")) then |
-- TitanPanelButton_UpdateButton(TITAN_LANGUAGECYCLE_ID); |
-- end |
-- if (IsAddOnLoaded("FuBar")) then |
-- LanguageCycleFuBar:UpdateText() |
-- end |
end |
function Language_Cycle_Set_Party_Checkbutton() |
if (LANGUAGE_CYCLE.translate_group) then |
Language_Cycle_Party_Toggle:SetChecked(1); |
else |
Language_Cycle_Party_Toggle:SetChecked(0); |
end |
end |
function Language_Cycle_Set_Text_Color() |
if (LANGUAGE_CYCLE.translate_group) then |
Language_Cycle_Button:GetNormalFontObject():SetTextColor(1, 1, 1); |
else |
Language_Cycle_Button:GetNormalFontObject():SetTextColor(.5, 1, .5); |
end |
end |
function Language_Cycle_Slash(arg) |
if (arg == "" or arg == nil) then |
Language_Cycle_Cycle(); |
elseif (arg == "ver" or arg == "version") then |
Language_Cycle_Add_Message("LanguageCycle version: " .. LC_version); |
elseif (arg == "clear") then |
Language_Cycle_Clear(); |
elseif (arg == "stat" or arg == "status") then |
local msg = "Speaking: " .. LANGUAGE_CYCLE.saved_language[LC_player_id] .. "; Guild/Party translation is "; |
if (LANGUAGE_CYCLE.translate_group) then |
msg = msg .. "on."; |
else |
msg = msg .. "off."; |
end |
Language_Cycle_Add_Message(msg); |
elseif (arg == "party" or arg == "guild" or arg == "group" or arg =="toggle") then |
Language_Cycle_Toggle_Group(true); |
elseif (arg == "show" or arg == "hide") then |
Language_Cycle_Panel_Visible(); |
elseif (arg == "mm" or arg == "MM") then |
if (LANGUAGE_CYCLE.minimapIcon.hide == false) then |
LibStub("LibDBIcon-1.0"):Hide("LanguageCycle") |
LANGUAGE_CYCLE.minimapIcon.hide = true |
else |
LibStub("LibDBIcon-1.0"):Show("LanguageCycle") |
LANGUAGE_CYCLE.minimapIcon.hide = false |
end |
elseif (arg == "help") then |
local t = 0; |
while LC_Help_Text[t] ~= nil do |
DEFAULT_CHAT_FRAME:AddMessage(LC_Help_Text[t],0.0, 1.0, 0.0); |
t = t + 1; |
end |
end |
end |
function Language_Cycle_Clear() |
LANGUAGE_CYCLE.saved_language[LC_player_id] = nil; |
LANGUAGE_CYCLE.translate_group = true; |
Language_Cycle_Add_Message(string.format("Cleared language for %s", LC_player_name)); |
Language_Cycle_Button:SetText("Pref Cleared..."); |
Language_Cycle_Set_Text_Color(); |
end |
function Language_Cycle_Add_Message(msg) |
DEFAULT_CHAT_FRAME:AddMessage(msg,0.0,1.0,0.0); |
end |
## Interface: 50200 |
## Title: LanguageCycle |
## Version: 5.0.4.a |
## Description: Adds key binding and slash commands for selecting a character's current language. |
## Notes: Adds key binding and slash commands for selecting a character's current language. Now with LDB support! |
## Author: Halya of Argent Dawn EU. |
## X-OriginalAuthor: aghokala@gmail.com. |
## X-UpdatesBy: Nhani of Earthen Ring EU. |
## X-Maintainers: Halya of Argent Dawn EU, Aenott of Earthen Ring EU. |
## SavedVariables: LANGUAGE_CYCLE |
LanguageCycle.xml |
--[[ |
Name: DBIcon-1.0 |
Revision: $Rev: 25 $ |
Author(s): Rabbit (rabbit.magtheridon@gmail.com) |
Description: Allows addons to register to recieve a lightweight minimap icon as an alternative to more heavy LDB displays. |
Dependencies: LibStub |
License: GPL v2 or later. |
]] |
--[[ |
Copyright (C) 2008-2011 Rabbit |
This program is free software; you can redistribute it and/or |
modify it under the terms of the GNU General Public License |
as published by the Free Software Foundation; either version 2 |
of the License, or (at your option) any later version. |
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
]] |
----------------------------------------------------------------------- |
-- DBIcon-1.0 |
-- |
-- Disclaimer: Most of this code was ripped from Barrel but fixed, streamlined |
-- and cleaned up a lot so that it no longer sucks. |
-- |
local DBICON10 = "LibDBIcon-1.0" |
local DBICON10_MINOR = tonumber(("$Rev: 25 $"):match("(%d+)")) |
if not LibStub then error(DBICON10 .. " requires LibStub.") end |
local ldb = LibStub("LibDataBroker-1.1", true) |
if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end |
local lib = LibStub:NewLibrary(DBICON10, DBICON10_MINOR) |
if not lib then return end |
lib.disabled = lib.disabled or nil |
lib.objects = lib.objects or {} |
lib.callbackRegistered = lib.callbackRegistered or nil |
lib.notCreated = lib.notCreated or {} |
function lib:IconCallback(event, name, key, value, dataobj) |
if lib.objects[name] then |
if key == "icon" then |
lib.objects[name].icon:SetTexture(value) |
elseif key == "iconCoords" then |
lib.objects[name].icon:UpdateCoord() |
end |
end |
end |
if not lib.callbackRegistered then |
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__icon", "IconCallback") |
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconCoords", "IconCallback") |
lib.callbackRegistered = true |
end |
-- Tooltip code ripped from StatBlockCore by Funkydude |
local function getAnchors(frame) |
local x, y = frame:GetCenter() |
if not x or not y then return "CENTER" end |
local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or "" |
local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM" |
return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf |
end |
local function onEnter(self) |
if self.isMoving then return end |
local obj = self.dataObject |
if obj.OnTooltipShow then |
GameTooltip:SetOwner(self, "ANCHOR_NONE") |
GameTooltip:SetPoint(getAnchors(self)) |
obj.OnTooltipShow(GameTooltip) |
GameTooltip:Show() |
elseif obj.OnEnter then |
obj.OnEnter(self) |
end |
end |
local function onLeave(self) |
local obj = self.dataObject |
GameTooltip:Hide() |
if obj.OnLeave then obj.OnLeave(self) end |
end |
-------------------------------------------------------------------------------- |
local onClick, onMouseUp, onMouseDown, onDragStart, onDragEnd, updatePosition |
do |
local minimapShapes = { |
["ROUND"] = {true, true, true, true}, |
["SQUARE"] = {false, false, false, false}, |
["CORNER-TOPLEFT"] = {false, false, false, true}, |
["CORNER-TOPRIGHT"] = {false, false, true, false}, |
["CORNER-BOTTOMLEFT"] = {false, true, false, false}, |
["CORNER-BOTTOMRIGHT"] = {true, false, false, false}, |
["SIDE-LEFT"] = {false, true, false, true}, |
["SIDE-RIGHT"] = {true, false, true, false}, |
["SIDE-TOP"] = {false, false, true, true}, |
["SIDE-BOTTOM"] = {true, true, false, false}, |
["TRICORNER-TOPLEFT"] = {false, true, true, true}, |
["TRICORNER-TOPRIGHT"] = {true, false, true, true}, |
["TRICORNER-BOTTOMLEFT"] = {true, true, false, true}, |
["TRICORNER-BOTTOMRIGHT"] = {true, true, true, false}, |
} |
function updatePosition(button) |
local angle = math.rad(button.db and button.db.minimapPos or button.minimapPos or 225) |
local x, y, q = math.cos(angle), math.sin(angle), 1 |
if x < 0 then q = q + 1 end |
if y > 0 then q = q + 2 end |
local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND" |
local quadTable = minimapShapes[minimapShape] |
if quadTable[q] then |
x, y = x*80, y*80 |
else |
local diagRadius = 103.13708498985 --math.sqrt(2*(80)^2)-10 |
x = math.max(-80, math.min(x*diagRadius, 80)) |
y = math.max(-80, math.min(y*diagRadius, 80)) |
end |
button:SetPoint("CENTER", Minimap, "CENTER", x, y) |
end |
end |
function onClick(self, b) if self.dataObject.OnClick then self.dataObject.OnClick(self, b) end end |
function onMouseDown(self) self.isMouseDown = true; self.icon:UpdateCoord() end |
function onMouseUp(self) self.isMouseDown = false; self.icon:UpdateCoord() end |
do |
local function onUpdate(self) |
local mx, my = Minimap:GetCenter() |
local px, py = GetCursorPosition() |
local scale = Minimap:GetEffectiveScale() |
px, py = px / scale, py / scale |
if self.db then |
self.db.minimapPos = math.deg(math.atan2(py - my, px - mx)) % 360 |
else |
self.minimapPos = math.deg(math.atan2(py - my, px - mx)) % 360 |
end |
updatePosition(self) |
end |
function onDragStart(self) |
self:LockHighlight() |
self.isMouseDown = true |
self.icon:UpdateCoord() |
self:SetScript("OnUpdate", onUpdate) |
self.isMoving = true |
GameTooltip:Hide() |
end |
end |
function onDragStop(self) |
self:SetScript("OnUpdate", nil) |
self.isMouseDown = false |
self.icon:UpdateCoord() |
self:UnlockHighlight() |
self.isMoving = nil |
end |
local defaultCoords = {0, 1, 0, 1} |
local function updateCoord(self) |
local coords = self:GetParent().dataObject.iconCoords or defaultCoords |
local deltaX, deltaY = 0, 0 |
if not self:GetParent().isMouseDown then |
deltaX = (coords[2] - coords[1]) * 0.05 |
deltaY = (coords[4] - coords[3]) * 0.05 |
end |
self:SetTexCoord(coords[1] + deltaX, coords[2] - deltaX, coords[3] + deltaY, coords[4] - deltaY) |
end |
local function createButton(name, object, db) |
local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap) |
button.dataObject = object |
button.db = db |
button:SetFrameStrata("MEDIUM") |
button:SetWidth(31); button:SetHeight(31) |
button:SetFrameLevel(8) |
button:RegisterForClicks("anyUp") |
button:RegisterForDrag("LeftButton") |
button:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight") |
local overlay = button:CreateTexture(nil, "OVERLAY") |
overlay:SetWidth(53); overlay:SetHeight(53) |
overlay:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder") |
overlay:SetPoint("TOPLEFT") |
local background = button:CreateTexture(nil, "BACKGROUND") |
background:SetWidth(20); background:SetHeight(20) |
background:SetTexture("Interface\\Minimap\\UI-Minimap-Background") |
background:SetPoint("TOPLEFT", 7, -5) |
local icon = button:CreateTexture(nil, "ARTWORK") |
icon:SetWidth(17); icon:SetHeight(17) |
icon:SetTexture(object.icon) |
icon:SetPoint("TOPLEFT", 7, -6) |
button.icon = icon |
button.isMouseDown = false |
icon.UpdateCoord = updateCoord |
icon:UpdateCoord() |
button:SetScript("OnEnter", onEnter) |
button:SetScript("OnLeave", onLeave) |
button:SetScript("OnClick", onClick) |
if not db or not db.lock then |
button:SetScript("OnDragStart", onDragStart) |
button:SetScript("OnDragStop", onDragStop) |
end |
button:SetScript("OnMouseDown", onMouseDown) |
button:SetScript("OnMouseUp", onMouseUp) |
lib.objects[name] = button |
if lib.loggedIn then |
updatePosition(button) |
if not db or not db.hide then button:Show() |
else button:Hide() end |
end |
end |
-- We could use a metatable.__index on lib.objects, but then we'd create |
-- the icons when checking things like :IsRegistered, which is not necessary. |
local function check(name) |
if lib.notCreated[name] then |
createButton(name, lib.notCreated[name][1], lib.notCreated[name][2]) |
lib.notCreated[name] = nil |
end |
end |
lib.loggedIn = lib.loggedIn or false |
-- Wait a bit with the initial positioning to let any GetMinimapShape addons |
-- load up. |
if not lib.loggedIn then |
local f = CreateFrame("Frame") |
f:SetScript("OnEvent", function() |
for _, object in pairs(lib.objects) do |
updatePosition(object) |
if not lib.disabled and (not object.db or not object.db.hide) then object:Show() |
else object:Hide() end |
end |
lib.loggedIn = true |
f:SetScript("OnEvent", nil) |
f = nil |
end) |
f:RegisterEvent("PLAYER_LOGIN") |
end |
local function getDatabase(name) |
return lib.notCreated[name] and lib.notCreated[name][2] or lib.objects[name].db |
end |
function lib:Register(name, object, db) |
if not object.icon then error("Can't register LDB objects without icons set!") end |
if lib.objects[name] or lib.notCreated[name] then error("Already registered, nubcake.") end |
if not lib.disabled and (not db or not db.hide) then |
createButton(name, object, db) |
else |
lib.notCreated[name] = {object, db} |
end |
end |
function lib:Lock(name) |
if not lib:IsRegistered(name) then return end |
if lib.objects[name] then |
lib.objects[name]:SetScript("OnDragStart", nil) |
lib.objects[name]:SetScript("OnDragStop", nil) |
end |
local db = getDatabase(name) |
if db then db.lock = true end |
end |
function lib:Unlock(name) |
if not lib:IsRegistered(name) then return end |
if lib.objects[name] then |
lib.objects[name]:SetScript("OnDragStart", onDragStart) |
lib.objects[name]:SetScript("OnDragStop", onDragStop) |
end |
local db = getDatabase(name) |
if db then db.lock = nil end |
end |
function lib:Hide(name) |
if not lib.objects[name] then return end |
lib.objects[name]:Hide() |
end |
function lib:Show(name) |
if lib.disabled then return end |
check(name) |
lib.objects[name]:Show() |
updatePosition(lib.objects[name]) |
end |
function lib:IsRegistered(name) |
return (lib.objects[name] or lib.notCreated[name]) and true or false |
end |
function lib:Refresh(name, db) |
if lib.disabled then return end |
check(name) |
local button = lib.objects[name] |
if db then button.db = db end |
updatePosition(button) |
if not button.db or not button.db.hide then |
button:Show() |
else |
button:Hide() |
end |
if not button.db or not button.db.lock then |
button:SetScript("OnDragStart", onDragStart) |
button:SetScript("OnDragStop", onDragStop) |
else |
button:SetScript("OnDragStart", nil) |
button:SetScript("OnDragStop", nil) |
end |
end |
function lib:GetMinimapButton(name) |
return lib.objects[name] |
end |
function lib:EnableLibrary() |
lib.disabled = nil |
for name, object in pairs(lib.objects) do |
if not object.db or not object.db.hide then |
object:Show() |
updatePosition(object) |
end |
end |
for name, data in pairs(lib.notCreated) do |
if not data.db or not data.db.hide then |
createButton(name, data[1], data[2]) |
lib.notCreated[name] = nil |
end |
end |
end |
function lib:DisableLibrary() |
lib.disabled = true |
for name, object in pairs(lib.objects) do |
object:Hide() |
end |
end |
assert(LibStub, "LibDataBroker-1.1 requires LibStub") |
assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0") |
local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4) |
if not lib then return end |
oldminor = oldminor or 0 |
lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib) |
lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {} |
local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks |
if oldminor < 2 then |
lib.domt = { |
__metatable = "access denied", |
__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end, |
} |
end |
if oldminor < 3 then |
lib.domt.__newindex = function(self, key, value) |
if not attributestorage[self] then attributestorage[self] = {} end |
if attributestorage[self][key] == value then return end |
attributestorage[self][key] = value |
local name = namestorage[self] |
if not name then return end |
callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self) |
callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self) |
callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self) |
callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self) |
end |
end |
if oldminor < 2 then |
function lib:NewDataObject(name, dataobj) |
if self.proxystorage[name] then return end |
if dataobj then |
assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table") |
self.attributestorage[dataobj] = {} |
for i,v in pairs(dataobj) do |
self.attributestorage[dataobj][i] = v |
dataobj[i] = nil |
end |
end |
dataobj = setmetatable(dataobj or {}, self.domt) |
self.proxystorage[name], self.namestorage[dataobj] = dataobj, name |
self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj) |
return dataobj |
end |
end |
if oldminor < 1 then |
function lib:DataObjectIterator() |
return pairs(self.proxystorage) |
end |
function lib:GetDataObjectByName(dataobjectname) |
return self.proxystorage[dataobjectname] |
end |
function lib:GetNameByDataObject(dataobject) |
return self.namestorage[dataobject] |
end |
end |
if oldminor < 4 then |
local next = pairs(attributestorage) |
function lib:pairs(dataobject_or_name) |
local t = type(dataobject_or_name) |
assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)") |
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name |
assert(attributestorage[dataobj], "Data object not found") |
return next, attributestorage[dataobj], nil |
end |
local ipairs_iter = ipairs(attributestorage) |
function lib:ipairs(dataobject_or_name) |
local t = type(dataobject_or_name) |
assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)") |
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name |
assert(attributestorage[dataobj], "Data object not found") |
return ipairs_iter, attributestorage[dataobj], 0 |
end |
end |
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info |
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke |
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! |
local LibStub = _G[LIBSTUB_MAJOR] |
if not LibStub or LibStub.minor < LIBSTUB_MINOR then |
LibStub = LibStub or {libs = {}, minors = {} } |
_G[LIBSTUB_MAJOR] = LibStub |
LibStub.minor = LIBSTUB_MINOR |
function LibStub:NewLibrary(major, minor) |
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") |
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") |
local oldminor = self.minors[major] |
if oldminor and oldminor >= minor then return nil end |
self.minors[major], self.libs[major] = minor, self.libs[major] or {} |
return self.libs[major], oldminor |
end |
function LibStub:GetLibrary(major, silent) |
if not self.libs[major] and not silent then |
error(("Cannot find a library instance of %q."):format(tostring(major)), 2) |
end |
return self.libs[major], self.minors[major] |
end |
function LibStub:IterateLibraries() return pairs(self.libs) end |
setmetatable(LibStub, { __call = LibStub.GetLibrary }) |
end |
<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> |
--[[ $Id: CallbackHandler-1.0.lua 895 2009-12-06 16:28:55Z nevcairiel $ ]] |
local MAJOR, MINOR = "CallbackHandler-1.0", 5 |
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR) |
if not CallbackHandler then return end -- No upgrade needed |
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end} |
-- Lua APIs |
local tconcat = table.concat |
local assert, error, loadstring = assert, error, loadstring |
local setmetatable, rawset, rawget = setmetatable, rawset, rawget |
local next, select, pairs, type, tostring = next, select, pairs, type, tostring |
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded |
-- List them here for Mikk's FindGlobals script |
-- GLOBALS: geterrorhandler |
local xpcall = xpcall |
local function errorhandler(err) |
return geterrorhandler()(err) |
end |
local function CreateDispatcher(argCount) |
local code = [[ |
local next, xpcall, eh = ... |
local method, ARGS |
local function call() method(ARGS) end |
local function dispatch(handlers, ...) |
local index |
index, method = next(handlers) |
if not method then return end |
local OLD_ARGS = ARGS |
ARGS = ... |
repeat |
xpcall(call, eh) |
index, method = next(handlers, index) |
until not method |
ARGS = OLD_ARGS |
end |
return dispatch |
]] |
local ARGS, OLD_ARGS = {}, {} |
for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end |
code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", ")) |
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler) |
end |
local Dispatchers = setmetatable({}, {__index=function(self, argCount) |
local dispatcher = CreateDispatcher(argCount) |
rawset(self, argCount, dispatcher) |
return dispatcher |
end}) |
-------------------------------------------------------------------------- |
-- CallbackHandler:New |
-- |
-- target - target object to embed public APIs in |
-- RegisterName - name of the callback registration API, default "RegisterCallback" |
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback" |
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API. |
function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused) |
-- TODO: Remove this after beta has gone out |
assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused") |
RegisterName = RegisterName or "RegisterCallback" |
UnregisterName = UnregisterName or "UnregisterCallback" |
if UnregisterAllName==nil then -- false is used to indicate "don't want this method" |
UnregisterAllName = "UnregisterAllCallbacks" |
end |
-- we declare all objects and exported APIs inside this closure to quickly gain access |
-- to e.g. function names, the "target" parameter, etc |
-- Create the registry object |
local events = setmetatable({}, meta) |
local registry = { recurse=0, events=events } |
-- registry:Fire() - fires the given event/message into the registry |
function registry:Fire(eventname, ...) |
if not rawget(events, eventname) or not next(events[eventname]) then return end |
local oldrecurse = registry.recurse |
registry.recurse = oldrecurse + 1 |
Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...) |
registry.recurse = oldrecurse |
if registry.insertQueue and oldrecurse==0 then |
-- Something in one of our callbacks wanted to register more callbacks; they got queued |
for eventname,callbacks in pairs(registry.insertQueue) do |
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. |
for self,func in pairs(callbacks) do |
events[eventname][self] = func |
-- fire OnUsed callback? |
if first and registry.OnUsed then |
registry.OnUsed(registry, target, eventname) |
first = nil |
end |
end |
end |
registry.insertQueue = nil |
end |
end |
-- Registration of a callback, handles: |
-- self["method"], leads to self["method"](self, ...) |
-- self with function ref, leads to functionref(...) |
-- "addonId" (instead of self) with function ref, leads to functionref(...) |
-- all with an optional arg, which, if present, gets passed as first argument (after self if present) |
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]]) |
if type(eventname) ~= "string" then |
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2) |
end |
method = method or eventname |
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. |
if type(method) ~= "string" and type(method) ~= "function" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2) |
end |
local regfunc |
if type(method) == "string" then |
-- self["method"] calling style |
if type(self) ~= "table" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2) |
elseif self==target then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2) |
elseif type(self[method]) ~= "function" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2) |
end |
if select("#",...)>=1 then -- this is not the same as testing for arg==nil! |
local arg=select(1,...) |
regfunc = function(...) self[method](self,arg,...) end |
else |
regfunc = function(...) self[method](self,...) end |
end |
else |
-- function ref with self=object or self="addonId" |
if type(self)~="table" and type(self)~="string" then |
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string expected.", 2) |
end |
if select("#",...)>=1 then -- this is not the same as testing for arg==nil! |
local arg=select(1,...) |
regfunc = function(...) method(arg,...) end |
else |
regfunc = method |
end |
end |
if events[eventname][self] or registry.recurse<1 then |
-- if registry.recurse<1 then |
-- we're overwriting an existing entry, or not currently recursing. just set it. |
events[eventname][self] = regfunc |
-- fire OnUsed callback? |
if registry.OnUsed and first then |
registry.OnUsed(registry, target, eventname) |
end |
else |
-- we're currently processing a callback in this registry, so delay the registration of this new entry! |
-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency |
registry.insertQueue = registry.insertQueue or setmetatable({},meta) |
registry.insertQueue[eventname][self] = regfunc |
end |
end |
-- Unregister a callback |
target[UnregisterName] = function(self, eventname) |
if not self or self==target then |
error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2) |
end |
if type(eventname) ~= "string" then |
error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2) |
end |
if rawget(events, eventname) and events[eventname][self] then |
events[eventname][self] = nil |
-- Fire OnUnused callback? |
if registry.OnUnused and not next(events[eventname]) then |
registry.OnUnused(registry, target, eventname) |
end |
end |
if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then |
registry.insertQueue[eventname][self] = nil |
end |
end |
-- OPTIONAL: Unregister all callbacks for given selfs/addonIds |
if UnregisterAllName then |
target[UnregisterAllName] = function(...) |
if select("#",...)<1 then |
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2) |
end |
if select("#",...)==1 and ...==target then |
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2) |
end |
for i=1,select("#",...) do |
local self = select(i,...) |
if registry.insertQueue then |
for eventname, callbacks in pairs(registry.insertQueue) do |
if callbacks[self] then |
callbacks[self] = nil |
end |
end |
end |
for eventname, callbacks in pairs(events) do |
if callbacks[self] then |
callbacks[self] = nil |
-- Fire OnUnused callback? |
if registry.OnUnused and not next(callbacks) then |
registry.OnUnused(registry, target, eventname) |
end |
end |
end |
end |
end |
end |
return registry |
end |
-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it |
-- try to upgrade old implicit embeds since the system is selfcontained and |
-- relies on closures to work. |
LanguageCycle v4.2 |
---What this mod does--- |
LanguageCycle provides a quick way for role-players to know what language their character is speaking and easily change that language. It also allows users to speak a non-default language in most channels, but automatically speak in either Common or Orcish (determined by faction) in party, raid and guild chat, preventing the need to constantly switch languages. |
---What this mod DOES NOT do--- |
This is not a translation mod. It will not allow you to speak or understand any languages which your character does not know. |
---Install--- |
Unzip files to the Interface/AddOns/ folder within your main World of Warcraft folder. This should automatically create two new sub-folders. One folder for LanguageCycle and one for TitanLanguageCycle. If you do not use Titan Panel, you do not need the TitanLanguageCycle folder or files, but they do no harm. The Titan LanguageCycle plugin requires both sets of files. |
---Features--- |
LanguageCycle adds a button and a small pop-up panel to the user interface for selecting which language your character will use. The button displays the currently-selected language. When clicked, your selected language will change to the next available language for your character. e.g. Switching from Common to Darnassian for a Night Elf character. Characters who can only speak one language are unaffected (and have no need for this mod!). Cycling through available languages may also be done via a slash command or a key binding. |
By default, LanguageCycle will automatically send /party, /raid and /guild messages in the character's base faction language (Common or Orcish). e.g. You can be speaking Darnassian in /say, but your messages to /party will be in Common. This option may be turned off either by deselcting the checkbox or using a slash command. |
Which language has been selected is saved per character. e.g. Setting Troll as the language for one character will have no affect on any other Troll characters you use. |
The setting of the /party, /raid and /guild language override is saved, but not per character. e.g. If you turn off the checkbox while playing one character, logging in with a different character will maintain the same setting, and the checkbox will be off. |
---UI Mods--- |
In normal usage, a button appears on the screen. Left-clicking on the button cycles through available languages. When moving the mouse near the button, a small pop-up panel appears around the button with two additional options- A checkbox for /party, /raid and /guild chat language and a close button to hide the entire UI. |
The checkbox is on by default. Checking it off will allow you to speak your current language in all channels. The text on the button displays in a light green color when this box is unchecked and white when checked. |
Clicking the close button will hide both the button and the pop-up panel. You can get the UI to reappear by using the slash command "/lc show". |
The UI may be moved anywhere on your screen by dragging on the text in the pop-up panel. |
If you do not want the pop-up panel to appear, right-click on the button. Right-clicking does NOT cause the language selection to cycle. In this compact state, the UI may not be dragged elsewhere on your screen. To have the pop-up panel appear again, right-click again. |
The location and visible status of the button is saved per character. |
---Slash Commands--- |
To cycle through your languages manually, use: |
/lc |
This is the same as left-clicking on the button (or the Titan Panel button). |
To toggle speaking your faction's base language in /party, /raid and /guild chat, use: |
/lc party |
/lc group |
/lc guild |
/lc toggle |
Any of the above commands will do the same thing. Each is the same as clicking the checkbox in the pop-up panel (or toggling the Titan Panel auto-translate option). |
To hide or show the visual UI, use: |
/lc show |
/lc hide |
Both commands do the same thing. If the button is visible, they are the same as clicking the close box. If the button is not visible, either command will make it reappear. |
When the UI is hidden, you can find out what LanguageCycle's current settings are with the command: |
/lc status |
This displays both your current language and the setting of group/party translation. |
---Key Bindings--- |
A key binding is available for cycling through your available languages. When used, the key binding is the same as left-clicking the button or using the /lc command. Look for "Language Cycle" within your key bindings window. |
---Known Issues--- |
This mod overrides the standard UI language selection menu. Selecting languages with the normal WoW UI will do nothing. If you do not wish to use this mod to control your languages, you should remove it from your Interface/AddOns/ folder. Using the Close box or the /lc hide command to remove the button from your screen is NOT sufficient. |
At this time, there are no other known issues with either the standard WoW UI or any other third-party mods. |
---Version History--- |
-4.2.2 |
Minimap icon should now save its position |
Added slashcommand to hide the minimap button |
LDB libs are now embedded |
-4.2 |
Updated toc version |
Added LDB support |
-4.0.1 |
Fixed depreciated code usage and updated toc |
-3.2 |
Updated toc version for 3.2.2. No code changes, mod still fully functional. |
-3.1.0 |
Updated toc version for patch 3.1, mod still fully functional. |
-3.0.3 |
Updated toc version and various comments/texts including this file. |
-3.0.2d |
After getting some help the default UI button works again. |
-3.0.2c |
Stripped all non-functional code to make the mod functional for Patch 3.0.2. UI functionality disabled. |
-2.03 - Apr. 7, 2008: |
Fixed an issue where Blizzard had corrected a typoed function call so LanguageCycle can find the proper function again. |
-2.02 - Dec. 31, 2006: |
Integrated the Titan panel plugin into the core (LanguageCycle) mod rather than keeping it a seperate one, for people who are directory concious. |
Integrated a new FuBar plugin so LanguageCycle now supports that aswell. Added a few ACE libraries because of this integration. |
Removed old additional TitanPanel plugin as it is no longer needed. |
-2.01 - Dec. 31, 2006: |
Added a few other new channels to the auto-translate feature (battlegrounds for one) |
Fixed and Readded the Titanpanel plugin as it seems to be working now. |
-2.00 - Dec. 26, 2006: |
Updated for WoW client 2.x. |
Changed a few inner works to ensure playing nicely with Blizzard's new protected calls. |
Removed the Titanpanel plugin for now until it can be tested with 2.x. |
-1.1.10900 - Jan. 5, 2006: |
Update TOC number to 10900 for WoW client patch 1.9.0 |
No other changes |
-1.1.1800 - Oct. 16, 2005: |
Update TOC number to 1800 for WoW client patch 1.8.0 |
Added Guild Officer channel to auto-translate feature. |
-1.1.1700 - Sept. 13, 2005: |
Update TOC number to 1700 for WoW client patch 1.7.0 |
No other changes |
-1.1.1600 - July 12, 2005: |
Updated TOC number to 1600 for WoW client patch 1.6.0. |
No other changes. |
-1.1.1500 - June 15, 2005: |
Added MyAddons support. |
Added Titan Panel plugin. |
-1.0.1 - June 7, 2005: |
Updated TOC number to 1500 for WoW client patch 1.5.0. |
Added Raid channel to auto-translation. |
-1.0.0 - April 11, 2005: |
First released version. |
---Contact info--- |
Questions and concerns may be sent to: |
aghokala@gmail.com |
---EOF--- |
<Bindings> |
<Binding name="Cycle Language" header="LANGUAGECYCLE"> |
Language_Cycle_Cycle(); |
</Binding> |
</Bindings> |
<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"> |
<!--@no-lib-strip@--> |
<Script file="Libs\LibStub\LibStub.lua"/> |
<Include file="Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml"/> |
<Script file="Libs\LibDataBroker-1.1\LibDataBroker-1.1.lua"/> |
<Script file="Libs\LibDBIcon-1.0\LibDBIcon-1.0.lua"/> |
<!--@end-no-lib-strip@--> |
</Ui> |