--[[-------------------------------------------------------------------- Copyright (C) 2009, 2010, 2011, 2012 Sidoine De Wispelaere. Copyright (C) 2012, 2013, 2014 Johnny C. Lam. See the file LICENSE.txt for copying permission. --]]---------------------------------------------------------------------- local OVALE, Ovale = ... Ovale = LibStub("AceAddon-3.0"):NewAddon(Ovale, OVALE, "AceEvent-3.0", "AceSerializer-3.0", "AceTimer-3.0") -- Export "Ovale" symbol to global namespace. _G["Ovale"] = Ovale --<private-static-properties> local AceGUI = LibStub("AceGUI-3.0") -- Localized strings table. local L = nil local format = string.format local next = next local pairs = pairs local select = select local strfind = string.find local strjoin = strjoin local strlen = string.len local strmatch = string.match local tostring = tostring local tostringall = tostringall -- FrameXML/RestrictedInfrastructure local type = type local unpack = unpack local wipe = wipe local API_GetItemInfo = GetItemInfo local API_GetTime = GetTime local API_IsInGroup = IsInGroup local API_RegisterAddonMessagePrefix = RegisterAddonMessagePrefix local API_SendAddonMessage = SendAddonMessage local API_UnitCanAttack = UnitCanAttack local API_UnitExists = UnitExists local API_UnitHasVehicleUI = UnitHasVehicleUI local API_UnitIsDead = UnitIsDead local DEFAULT_CHAT_FRAME = DEFAULT_CHAT_FRAME local LE_PARTY_CATEGORY_INSTANCE = LE_PARTY_CATEGORY_INSTANCE local OVALE_VERSION = "@project-version@" local REPOSITORY_KEYWORD = "@" .. "project-version" .. "@" -- Table of strings to display once per session. local self_oneTimeMessage = {} --</private-static-properties> --<public-static-properties> -- Project version number. Ovale.version = (OVALE_VERSION == REPOSITORY_KEYWORD) and "development version" or OVALE_VERSION -- Localization string table. Ovale.L = nil -- AceDB-3.0 database to handle SavedVariables (managed by OvaleOptions). Ovale.db = nil --the frame with the icons Ovale.frame = nil -- Checkbox and dropdown definitions from evaluating the script. Ovale.checkBox = {} Ovale.list = {} -- Checkbox and dropdown GUI controls. Ovale.checkBoxWidget = {} Ovale.listWidget = {} -- List if units that require refreshing the best action. Ovale.refreshNeeded = {} -- Prefix of messages received via CHAT_MSG_ADDON for Ovale. Ovale.MSG_PREFIX = OVALE --</public-static-properties> --<private-static-methods> local function OnCheckBoxValueChanged(widget) -- Reflect the value change into the profile (model). local name = widget:GetUserData("name") Ovale.db.profile.check[name] = widget:GetValue() Ovale:SendMessage("Ovale_CheckBoxValueChanged", name) end local function OnDropDownValueChanged(widget) -- Reflect the value change into the profile (model). local name = widget:GetUserData("name") Ovale.db.profile.list[name] = widget:GetValue() Ovale:SendMessage("Ovale_ListValueChanged", name) end --</private-static-methods> --<public-static-methods> function Ovale:OnInitialize() -- Register message prefix for the addon. API_RegisterAddonMessagePrefix(self.MSG_PREFIX) -- Localization. L = Ovale.L -- Key bindings. BINDING_HEADER_OVALE = OVALE local toggleCheckBox = L["Inverser la boîte à cocher "] BINDING_NAME_OVALE_CHECKBOX0 = toggleCheckBox .. "(1)" BINDING_NAME_OVALE_CHECKBOX1 = toggleCheckBox .. "(2)" BINDING_NAME_OVALE_CHECKBOX2 = toggleCheckBox .. "(3)" BINDING_NAME_OVALE_CHECKBOX3 = toggleCheckBox .. "(4)" BINDING_NAME_OVALE_CHECKBOX4 = toggleCheckBox .. "(5)" end function Ovale:OnEnable() self:RegisterEvent("CHAT_MSG_ADDON") self:RegisterEvent("PLAYER_ENTERING_WORLD") self:RegisterEvent("PLAYER_TARGET_CHANGED") self:RegisterMessage("Ovale_CombatStarted") self:RegisterMessage("Ovale_OptionChanged") self.frame = AceGUI:Create(OVALE .. "Frame") self:UpdateFrame() end function Ovale:OnDisable() self:UnregisterEvent("CHAT_MSG_ADDON") self:UnregisterEvent("PLAYER_ENTERING_WORLD") self:UnregisterEvent("PLAYER_TARGET_CHANGED") self:UnregisterMessage("Ovale_CombatEnded") self:UnregisterMessage("Ovale_OptionChanged") self.frame:Hide() end do local versionReply = {} local timer function Ovale:CHAT_MSG_ADDON(event, ...) local prefix, message, channel, sender = ... if prefix == self.MSG_PREFIX then local ok, msgType, version = self:Deserialize(message) if ok then if msgType == "V" then local msg = self:Serialize("VR", self.version) local channel = API_IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and "INSTANCE_CHAT" or "RAID" API_SendAddonMessage(self.MSG_PREFIX, msg, channel) elseif msgType == "VR" then versionReply[sender] = version end end end end function Ovale:VersionCheck() if not timer then wipe(versionReply) local message = self:Serialize("V", self.version) local channel = API_IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and "INSTANCE_CHAT" or "RAID" API_SendAddonMessage(self.MSG_PREFIX, message, channel) timer = self:ScheduleTimer("PrintVersionCheck", 3) end end function Ovale:PrintVersionCheck() if next(versionReply) then for sender, version in pairs(versionReply) do self:Print(">>> %s is using Ovale %s", sender, version) end else self:Print(">>> No other Ovale users present.") end timer = nil end end --Called when the player target change --Used to update the visibility e.g. if the user chose --to hide Ovale if a friendly unit is targeted function Ovale:PLAYER_ENTERING_WORLD() self:ClearOneTimeMessages() end function Ovale:PLAYER_TARGET_CHANGED() self.refreshNeeded.target = true self:UpdateVisibility() end function Ovale:Ovale_CombatStarted(event, atTime) self:UpdateVisibility() end function Ovale:Ovale_CombatEnded(event, atTime) self:UpdateVisibility() end function Ovale:Ovale_OptionChanged(event, eventType) if eventType == "visibility" then self:UpdateVisibility() else if eventType == "layout" then self.frame:UpdateFrame() end self:UpdateFrame() end end function Ovale:IsPreloaded(moduleList) local preloaded = true for _, moduleName in pairs(moduleList) do preloaded = preloaded and self[moduleName].ready end return preloaded end function Ovale:ToggleOptions() self.frame:ToggleOptions() end function Ovale:UpdateVisibility() local visible = true local profile = self.db.profile if not profile.apparence.enableIcons then visible = false elseif not self.frame.hider:IsVisible() then visible = false else if profile.apparence.hideVehicule and API_UnitHasVehicleUI("player") then visible = false end if profile.apparence.avecCible and not API_UnitExists("target") then visible = false end if profile.apparence.enCombat and not Ovale.OvaleFuture.inCombat then visible = false end if profile.apparence.targetHostileOnly and (API_UnitIsDead("target") or not API_UnitCanAttack("player", "target")) then visible = false end end if visible then self.frame:Show() else self.frame:Hide() end end function Ovale:ResetControls() wipe(self.checkBox) wipe(self.list) end function Ovale:UpdateControls() local profile = self.db.profile -- Create a new CheckBox widget for each checkbox declared in the script. wipe(self.checkBoxWidget) for name, checkBox in pairs(self.checkBox) do if checkBox.text then local widget = AceGUI:Create("CheckBox") -- XXX Workaround for GetItemInfo() possibly returning nil. local text = self:FinalizeString(checkBox.text) widget:SetLabel(text) if profile.check[name] == nil then profile.check[name] = checkBox.checked end if profile.check[name] then widget:SetValue(profile.check[name]) end widget:SetUserData("name", name) widget:SetCallback("OnValueChanged", OnCheckBoxValueChanged) self.frame:AddChild(widget) self.checkBoxWidget[name] = widget else self:OneTimeMessage("Warning: checkbox '%s' is used but not defined.", name) end end -- Create a new Dropdown widget for each list declared in the script. wipe(self.listWidget) for name, list in pairs(self.list) do if next(list.items) then local widget = AceGUI:Create("Dropdown") widget:SetList(list.items) if not profile.list[name] then profile.list[name] = list.default end if profile.list[name] then widget:SetValue(profile.list[name]) end widget:SetUserData("name", name) widget:SetCallback("OnValueChanged", OnDropDownValueChanged) self.frame:AddChild(widget) self.listWidget[name] = widget else self:OneTimeMessage("Warning: list '%s' is used but has no items.", name) end end end function Ovale:UpdateFrame() self.frame:ReleaseChildren() self.frame:UpdateIcons() self:UpdateControls() self:UpdateVisibility() end function Ovale:IsChecked(name) local widget = self.checkBoxWidget[name] return widget and widget:GetValue() end function Ovale:GetListValue(name) local widget = self.listWidget[name] return widget and widget:GetValue() end -- Set the k'th checkbox control to the specified on/off (true/false) value. function Ovale:SetCheckBox(k, on) local profile = self.db.profile for name, widget in pairs(self.checkBoxWidget) do if k == 0 then widget:SetValue(on) profile.check[name] = on break end k = k - 1 end end -- Toggle the k'th checkbox control. function Ovale:ToggleCheckBox(k) local profile = self.db.profile for name, widget in pairs(self.checkBoxWidget) do if k == 0 then local on = not widget:GetValue() widget:SetValue(on) profile.check[name] = on break end k = k - 1 end end function Ovale:FinalizeString(s) local item, id = strmatch(s, "^(item:)(.+)") if item then s = API_GetItemInfo(id) end return s end --[[ Return a string from the parameters. If the first parameter is a format string, use the remaining parameters as parameters for the format string; otherwise, concatenate all of the parameters together. --]] function Ovale:MakeString(s, ...) if s and strlen(s) > 0 then if (...) then if strfind(s, "%%%.%d") or strfind(s, "%%[%w]") then -- "s" looks like a format string. s = format(s, tostringall(...)) else s = strjoin(" ", s, tostringall(...)) end end else s = tostring(nil) end return s end -- Print the parameters to DEFAULT_CHAT_FRAME, headed by the name of the module. -- NOTE: This method is mirrored to the module prototype for new modules. function Ovale:Print(...) local name = self:GetName() local s = Ovale:MakeString(...) -- Match output format from AceConsole-3.0 Print() method. DEFAULT_CHAT_FRAME:AddMessage(format("|cff33ff99%s|r: %s", name, s)) end -- Print the error message and flag the next frame to be traced by OvaleDebug. -- NOTE: This method is mirrored to the module prototype for new modules. function Ovale:Error(...) local s = Ovale:MakeString(...) self:Print("Fatal error: %s", s) Ovale.OvaleDebug.bug = true end function Ovale:OneTimeMessage(...) local s = self:MakeString(...) if not self_oneTimeMessage[s] then self_oneTimeMessage[s] = true end end function Ovale:ClearOneTimeMessages() wipe(self_oneTimeMessage) end function Ovale:PrintOneTimeMessages() for s in pairs(self_oneTimeMessage) do if self_oneTimeMessage[s] ~= "printed" then self:Print(s) self_oneTimeMessage[s] = "printed" end end end --</public-static-methods> --<private-static-properties> --[[ Ovale module prototype. The module prototype has a dummy Log method to mimic the API of the state machine. This makes it easier to write module methods that are mirrored to the state machine. --]] do local function DoNothing() -- no-op end local modulePrototype = { Error = Ovale.Error, Log = DoNothing, Print = Ovale.Print, } Ovale:SetDefaultModulePrototype(modulePrototype) end --</private-static-properties>