From e78164f1352f7efc52ac7d8a94c923f44ab20fd6 Mon Sep 17 00:00:00 2001 From: Eyal Shilony Date: Sat, 11 Oct 2014 03:46:45 +0300 Subject: [PATCH] Complete rewrite of my old addon LonnyMenu. Change the way you sort and manage the menu in the options. Replace AceGui, AceConfig and AceDbOptions libraries with Libra. --- Broker_StartMenu.lua | 162 -- Broker_StartMenu.toc | 21 +- Broker_Tooltip.lua | 186 -- Core.lua | 32 +- Menu.lua | 157 ++ Options.lua | 250 --- SecureButtonsOverlay.lua | 111 -- Tooltip.lua | 202 ++ libs/AceConfig-3.0/AceConfig-3.0.lua | 57 - libs/AceConfig-3.0/AceConfig-3.0.xml | 8 - .../AceConfigCmd-3.0/AceConfigCmd-3.0.lua | 787 -------- .../AceConfigCmd-3.0/AceConfigCmd-3.0.xml | 4 - .../AceConfigDialog-3.0/AceConfigDialog-3.0.lua | 1940 -------------------- .../AceConfigDialog-3.0/AceConfigDialog-3.0.xml | 4 - .../AceConfigRegistry-3.0.lua | 347 ---- .../AceConfigRegistry-3.0.xml | 4 - libs/AceConfigRegistrar.lua | 76 - libs/AceDBOptions-3.0/AceDBOptions-3.0.lua | 420 ----- libs/AceDBOptions-3.0/AceDBOptions-3.0.xml | 4 - libs/AceGUI-3.0/AceGUI-3.0.lua | 805 -------- libs/AceGUI-3.0/AceGUI-3.0.xml | 28 - .../widgets/AceGUIContainer-BlizOptionsGroup.lua | 133 -- .../widgets/AceGUIContainer-DropDownGroup.lua | 157 -- libs/AceGUI-3.0/widgets/AceGUIContainer-Frame.lua | 310 ---- .../widgets/AceGUIContainer-InlineGroup.lua | 102 - .../widgets/AceGUIContainer-ScrollFrame.lua | 203 -- .../widgets/AceGUIContainer-SimpleGroup.lua | 69 - .../widgets/AceGUIContainer-TabGroup.lua | 365 ---- .../widgets/AceGUIContainer-TreeGroup.lua | 707 ------- libs/AceGUI-3.0/widgets/AceGUIContainer-Window.lua | 331 ---- libs/AceGUI-3.0/widgets/AceGUIWidget-Button.lua | 92 - libs/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua | 289 --- .../widgets/AceGUIWidget-ColorPicker.lua | 186 -- .../widgets/AceGUIWidget-DropDown-Items.lua | 471 ----- libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua | 717 -------- libs/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua | 256 --- libs/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua | 78 - libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua | 144 -- .../widgets/AceGUIWidget-InteractiveLabel.lua | 101 - .../AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua | 232 --- libs/AceGUI-3.0/widgets/AceGUIWidget-Label.lua | 162 -- .../widgets/AceGUIWidget-MultiLineEditBox.lua | 345 ---- libs/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua | 281 --- libs/EasyDisplay.lua | 13 + libs/Libra-26/AceDBControls.lua | 340 ++++ libs/Libra-26/Addon.lua | 148 ++ libs/Libra-26/Button.lua | 30 + libs/Libra-26/Core.lua | 61 + libs/Libra-26/Dropdown.lua | 547 ++++++ libs/Libra-26/Editbox.lua | 29 + libs/Libra-26/Libra.xml | 14 + libs/Libra-26/OptionsFrame.lua | 496 +++++ libs/Libra-26/ScrollFrame.lua | 137 ++ libs/Libra-26/Slider.lua | 54 + libs/Libra-26/UIPanel.lua | 102 + loc/enUS.lua | 9 +- options/Accessibility.lua | 87 + options/General.lua | 113 ++ options/Menu.lua | 119 ++ options/Profiles.lua | 35 + options/UI.lua | 328 ++++ 61 files changed, 3035 insertions(+), 10963 deletions(-) delete mode 100644 Broker_StartMenu.lua delete mode 100644 Broker_Tooltip.lua create mode 100644 Menu.lua delete mode 100644 Options.lua delete mode 100644 SecureButtonsOverlay.lua create mode 100644 Tooltip.lua delete mode 100644 libs/AceConfig-3.0/AceConfig-3.0.lua delete mode 100644 libs/AceConfig-3.0/AceConfig-3.0.xml delete mode 100644 libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua delete mode 100644 libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.xml delete mode 100644 libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua delete mode 100644 libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.xml delete mode 100644 libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua delete mode 100644 libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.xml delete mode 100644 libs/AceConfigRegistrar.lua delete mode 100644 libs/AceDBOptions-3.0/AceDBOptions-3.0.lua delete mode 100644 libs/AceDBOptions-3.0/AceDBOptions-3.0.xml delete mode 100644 libs/AceGUI-3.0/AceGUI-3.0.lua delete mode 100644 libs/AceGUI-3.0/AceGUI-3.0.xml delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIContainer-BlizOptionsGroup.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIContainer-DropDownGroup.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIContainer-Frame.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIContainer-InlineGroup.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIContainer-ScrollFrame.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIContainer-SimpleGroup.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIContainer-TabGroup.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIContainer-Window.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-Button.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown-Items.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-InteractiveLabel.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-Label.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua delete mode 100644 libs/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua create mode 100644 libs/Libra-26/AceDBControls.lua create mode 100644 libs/Libra-26/Addon.lua create mode 100644 libs/Libra-26/Button.lua create mode 100644 libs/Libra-26/Core.lua create mode 100644 libs/Libra-26/Dropdown.lua create mode 100644 libs/Libra-26/Editbox.lua create mode 100644 libs/Libra-26/Libra.xml create mode 100644 libs/Libra-26/OptionsFrame.lua create mode 100644 libs/Libra-26/ScrollFrame.lua create mode 100644 libs/Libra-26/Slider.lua create mode 100644 libs/Libra-26/UIPanel.lua create mode 100644 options/Accessibility.lua create mode 100644 options/General.lua create mode 100644 options/Menu.lua create mode 100644 options/Profiles.lua create mode 100644 options/UI.lua diff --git a/Broker_StartMenu.lua b/Broker_StartMenu.lua deleted file mode 100644 index 2b09082..0000000 --- a/Broker_StartMenu.lua +++ /dev/null @@ -1,162 +0,0 @@ ---[[ - Copyright (c) 2014 Eyal Shilony - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -]] - -local addonName, addon = ... -local dropdown = CreateFrame("Frame", "StartMenuFrame", nil, "UIDropDownMenuTemplate") -local display = LibStub("EasyDisplay-1.0") -local L = LibStub("AceLocale-3.0"):GetLocale(addonName) -dropdown:Hide() - -local menu = { } -local disabledItems = { "talents" } - -local function insertItem(name, order) - local interface = display:GetInterface(name) - if interface and order > 0 then - local entry = { - order = order, - name = name, - text = interface.title, - icon = interface.icon, - notCheckable = 1, - func = function() display:DisplayInterface(name) end, - } - - if interface.button then - entry.button = interface.button - end - - table.insert(menu, entry) - end -end - -local function insertSimpleItem(text, func) - table.insert(menu, { - text = text, - notCheckable = 1, - func = func, - }) -end - -local function insertSeparator() - if #menu > 0 then - table.insert(menu, { - text = "", - notCheckable = 1, - disabled = true, - }) - end -end - -local function comp(a, b) - return a.order < b.order -end - -DropDownList1:HookScript("OnShow", function(self) - if InCombatLockdown() then - return - end - addon:RemoveSecureButtonsOverlay() - if addon:IsMenuVisible() then - addon:AddSecureButtonsOverlay(menu) - end -end) - -function addon:BuildMenu(brokerDisplayButton) - if not self.updateMenu then - return - end - - wipe(menu) - for name, order in pairs(self.db.profile.order) do - insertItem(name, order) - end - table.sort(menu, comp) - - if not self.db.profile.hideLogoutButtons then - insertSeparator() - insertSimpleItem(LOGOUT, function() - Logout() - HideUIPanel(GameMenuFrame) - end) - end - - if not self.db.profile.hideLogoutButtons then - insertSimpleItem(EXIT_GAME, function() - Quit() - HideUIPanel(GameMenuFrame) - end) - end - - if not self.db.profile.hideReloadUIButton then - insertSeparator() - insertSimpleItem(L["Reload UI"], function() - ReloadUI() - end) - end - - if not self.db.profile.hideOptionsButton then - insertSeparator() - insertSimpleItem(L["Options"], function() - if not InterfaceOptionsFrame:IsVisible() then - HideUIPanel(GameMenuFrame) - InterfaceOptionsFrame_OpenToCategory(addon.name) - else - HideUIPanel(InterfaceOptionsFrame) - end - end) - end - - self.updateMenu = false -end - -function addon:OpenMenu(frame, button) - local name - local isLeftButton = self.db.profile.mouseButton == 1 and button == "LeftButton" - local isRightButton = self.db.profile.mouseButton == 2 and button == "RightButton" - - for i, v in pairs(self.db.profile.accessibility) do - if not IsModifierKeyDown() and v.modifier == 4 - or IsAltKeyDown() and v.modifier == 1 - or IsControlKeyDown() and v.modifier == 2 - or IsShiftKeyDown() and v.modifier == 3 then - name = v.name - break - end - end - - if isLeftButton or isRightButton then - display:DisplayInterface(name) - else - EasyMenu(menu, dropdown, frame, 0, 0, "MENU") - end -end - -function addon:IsMenuVisible() - local current = UIDropDownMenu_GetCurrentDropDown() - if current and current == dropdown and DropDownList1:IsShown() then - return true - else - return false - end -end \ No newline at end of file diff --git a/Broker_StartMenu.toc b/Broker_StartMenu.toc index e29019d..87f5bfe 100644 --- a/Broker_StartMenu.toc +++ b/Broker_StartMenu.toc @@ -11,26 +11,23 @@ ## X-Website: http://wow.curseforge.com/addons/broker-startmenu/ ## X-License: MIT. -## SavedVariables: Broker_StartMenuDB +## SavedVariables: Broker_StartMenuDb libs\LibStub.lua libs\CallbackHandler-1.0.lua libs\LibDataBroker-1.1.lua - libs\AceLocale-3.0\AceLocale-3.0.xml -libs\AceGUI-3.0\AceGUI-3.0.xml -libs\AceConfig-3.0\AceConfig-3.0.xml libs\AceDB-3.0\AceDB-3.0.xml -libs\AceDBOptions-3.0\AceDBOptions-3.0.xml - +libs\Libra-26\Libra.xml libs\EasyDisplay.lua -libs\AceConfigRegistrar.lua loc\enUS.lua -Broker_Tooltip.lua -Broker_Menu.lua - -SecureButtonsOverlay.lua +Tooltip.lua +Menu.lua Core.lua -Options.lua +options\UI.lua +options\General.lua +options\Accessibility.lua +options\Menu.lua +options\Profiles.lua \ No newline at end of file diff --git a/Broker_Tooltip.lua b/Broker_Tooltip.lua deleted file mode 100644 index cbc40d5..0000000 --- a/Broker_Tooltip.lua +++ /dev/null @@ -1,186 +0,0 @@ ---[[ - Copyright (c) 2014 Eyal Shilony - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -]] - -local addonName, addon = ... -local display = LibStub("EasyDisplay-1.0") -local L = LibStub("AceLocale-3.0"):GetLocale(addonName) - -local function getTotalMemUsage() - UpdateAddOnMemoryUsage() - - local long, short - local totalMem = 0 - - for i=1, GetNumAddOns(), 1 do - totalMem = totalMem + GetAddOnMemoryUsage(i) - end - - if totalMem > 0 then - if totalMem > 1000 then - totalMem = totalMem / 1000 - short = format("%.2f MB", totalMem) - long = format(TOTAL_MEM_MB_ABBR, totalMem) - else - short = format("%.0f KB", totalMem) - long = format(TOTAL_MEM_KB_ABBR, totalMem) - end - end - - return totalMem, long, short -end - -local topAddOns = { } -local numAddOns = 0 -local tooltip = GameTooltip - -function addon:UpdateTooltip() - local db = self.db.profile - - if db.hideTooltip then - return - end - - if numAddOns ~= db.numAddOns then - for i=1, db.numAddOns do - topAddOns[i] = { value = 0, name = "" } - end - numAddOns = db.numAddOns - end - - local text = "" - local i, j, k = 0, 0, 0 - - tooltip:ClearLines() - - tooltip:AddLine(self.name, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - - -- latency - local _, _, latencyHome, latencyWorld = GetNetStats() - text = format(MAINMENUBAR_LATENCY_LABEL, latencyHome, latencyWorld) - tooltip:AddLine(" ") - tooltip:AddLine(text, 1.0, 1.0, 1.0) - if SHOW_NEWBIE_TIPS == "1" then - tooltip:AddLine(NEWBIE_TOOLTIP_LATENCY, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - end - tooltip:AddLine(" ") - - -- framerate - text = format(MAINMENUBAR_FPS_LABEL, GetFramerate()) - tooltip:AddLine(text, 1.0, 1.0, 1.0) - if SHOW_NEWBIE_TIPS == "1" then - tooltip:AddLine(NEWBIE_TOOLTIP_FRAMERATE, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - end - - local bandwidth = GetAvailableBandwidth() - if not bandwidth == 0 then - tooltip:AddLine(" ") - text = format(MAINMENUBAR_BANDWIDTH_LABEL, GetAvailableBandwidth()) - tooltip:AddLine(text, 1.0, 1.0, 1.0) - if SHOW_NEWBIE_TIPS == "1" then - tooltip:AddLine(NEWBIE_TOOLTIP_BANDWIDTH, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - end - end - - local percent = floor(GetDownloadedPercentage() * 100 + 0.5) - if not percent == 0 then - tooltip:AddLine(" ") - text = format(MAINMENUBAR_DOWNLOAD_PERCENT_LABEL, percent) - tooltip:AddLine(text, 1.0, 1.0, 1.0) - if ( SHOW_NEWBIE_TIPS == "1" ) then - tooltip:AddLine(NEWBIE_TOOLTIP_DOWNLOAD_PERCENT, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - end - end - - -- memory - local totalMem, totalText = getTotalMemUsage() - - if totalMem > 0 then - local mem - - for i = 1, db.numAddOns, 1 do - topAddOns[i].value = 0 - end - - for i = 1, GetNumAddOns(), 1 do - mem = GetAddOnMemoryUsage(i) - for j = 1, db.numAddOns, 1 do - if mem > topAddOns[j].value then - for k = db.numAddOns, 1, -1 do - if k == j then - topAddOns[k].value = mem - topAddOns[k].name = GetAddOnInfo(i) - break - elseif k ~= 1 then - topAddOns[k].value = topAddOns[k-1].value - topAddOns[k].name = topAddOns[k-1].name - end - end - break - end - end - end - - tooltip:AddLine(" ") - tooltip:AddLine(totalText, 1.0, 1.0, 1.0) - if SHOW_NEWBIE_TIPS == "1" then - tooltip:AddLine(NEWBIE_TOOLTIP_MEMORY, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) - end - - for i = 1, db.numAddOns, 1 do - if topAddOns[i].value == 0 then - break - end - - local size = topAddOns[i].value - - if size > 1000 then - size = size / 1000 - text = format(ADDON_MEM_MB_ABBR, size, topAddOns[i].name) - else - text = format(ADDON_MEM_KB_ABBR, size, topAddOns[i].name) - end - - tooltip:AddLine(text, 1.0, 1.0, 1.0) - end - end - - -- accessibility - if not db.hideTooltipAccessibilityBindings then - tooltip:AddLine(" ") - - local text = "" - - for i, v in ipairs(db.accessibility) do - local mouseButton = addon.buttons[db.mouseButton] - if v.modifier == 4 then - text = ": |cffffffff" .. mouseButton .. "|r" - else - text = ": |cffffffff" .. mouseButton .. " + " .. addon.modifiers[v.modifier] .. "|r" - end - text = display:GetInterface(v.name).title .. text - tooltip:AddLine(text, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b) - end - end - - tooltip:Show() -end \ No newline at end of file diff --git a/Core.lua b/Core.lua index 172b4ea..69f65d5 100644 --- a/Core.lua +++ b/Core.lua @@ -22,17 +22,9 @@ ]] local addonName, addon = ... -local core = CreateFrame("Frame") - -core:RegisterEvent("PLAYER_LOGIN") -core:RegisterEvent("PLAYER_REGEN_DISABLED") -local function onEvent(self, event, ...) - if self[event] and type(self[event]) == "function" then - self[event](self, ...) - end -end -core:SetScript('OnEvent', onEvent) +local core = LibStub("Libra"):NewAddon(addonName, addon) +addon.display = LibStub("EasyDisplay-1.0") addon.name = addonName:gsub("Broker_", "") local defaults = { @@ -44,7 +36,7 @@ local defaults = { hideLogoutButtons = true, hideReloadUIButton = false, hideOptionsButton = false, - order = { + menu = { character = 1, spellbook = 2, talents = 3, @@ -85,13 +77,13 @@ addon.buttons = { } addon.modifiers = { - ALT_KEY, - CTRL_KEY, + NONE, SHIFT_KEY, - NONE + CTRL_KEY, + ALT_KEY } -core:SetScript('OnUpdate', function(self, elapsed) +core:SetOnUpdate(function(self, elapsed) if addon:IsMenuVisible() or not addon.tooltip then return end @@ -107,10 +99,10 @@ core:SetScript('OnUpdate', function(self, elapsed) end end) -function core:PLAYER_LOGIN() +function core:OnInitialize() addon.updateMenu = true - addon.db = LibStub("AceDB-3.0"):New("LonnyMenuDB", defaults, true) + addon.db = LibStub("AceDB-3.0"):New("Broker_StartMenuDb", defaults, true) addon.db.RegisterCallback(addon, "OnProfileChanged", "BuildMenu") addon.db.RegisterCallback(addon, "OnProfileCopied", "BuildMenu") addon.db.RegisterCallback(addon, "OnProfileReset", "BuildMenu") @@ -143,10 +135,4 @@ function core:PLAYER_LOGIN() addon.tooltip = nil end }) - - addon:InitializeOptions() -end - -function core:PLAYER_REGEN_DISABLED() - addon:RemoveSecureButtonsOverlay() end \ No newline at end of file diff --git a/Menu.lua b/Menu.lua new file mode 100644 index 0000000..e7c0e86 --- /dev/null +++ b/Menu.lua @@ -0,0 +1,157 @@ +--[[ + Copyright (c) 2014 Eyal Shilony + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +]] + +local addonName, addon = ... +local dropdown = CreateFrame("Frame", "StartMenuFrame", nil, "UIDropDownMenuTemplate") +local display = LibStub("EasyDisplay-1.0") +local L = LibStub("AceLocale-3.0"):GetLocale(addonName) +dropdown:Hide() + +local menu = { } +local disabledItems = { "talents" } + +local function insertItem(name, order) + local interface = display:GetInterface(name) + if interface and order > 0 then + local entry = { + order = order, + name = name, + text = interface.title, + icon = interface.icon, + notCheckable = 1, + func = function() display:DisplayInterface(name) end, + attributes = { + ["type"] = "click", + ["clickbutton"] = interface.button, + } + } + + if interface.button then + entry.button = interface.button + end + + table.insert(menu, entry) + end +end + +local function insertSimpleItem(text, func) + table.insert(menu, { + text = text, + notCheckable = 1, + func = func, + }) +end + +local function insertSeparator() + if #menu > 0 then + table.insert(menu, { + text = "", + notCheckable = 1, + disabled = true, + }) + end +end + +local function comp(a, b) + return a.order < b.order +end + +function addon:BuildMenu(brokerDisplayButton) + if not self.updateMenu then + return + end + + wipe(menu) + for name, order in pairs(self.db.profile.menu) do + insertItem(name, order) + end + table.sort(menu, comp) + + if not self.db.profile.hideLogoutButtons then + insertSeparator() + insertSimpleItem(LOGOUT, function() + Logout() + HideUIPanel(GameMenuFrame) + end) + end + + if not self.db.profile.hideLogoutButtons then + insertSimpleItem(EXIT_GAME, function() + Quit() + HideUIPanel(GameMenuFrame) + end) + end + + if not self.db.profile.hideReloadUIButton then + insertSeparator() + insertSimpleItem(L["Reload UI"], function() + ReloadUI() + end) + end + + if not self.db.profile.hideOptionsButton then + insertSeparator() + insertSimpleItem(L["Options"], function() + if not InterfaceOptionsFrame:IsVisible() then + HideUIPanel(GameMenuFrame) + InterfaceOptionsFrame_OpenToCategory(addon.name) + InterfaceOptionsFrame_OpenToCategory(addon.name) + else + HideUIPanel(InterfaceOptionsFrame) + end + end) + end + + self.updateMenu = false +end + +function addon:OpenMenu(frame, button) + local name + local isLeftButton = self.db.profile.mouseButton == 1 and button == "LeftButton" + local isRightButton = self.db.profile.mouseButton == 2 and button == "RightButton" + + for _, v in pairs(self.db.profile.accessibility) do + if not IsModifierKeyDown() and v.modifier == 4 + or IsAltKeyDown() and v.modifier == 1 + or IsControlKeyDown() and v.modifier == 2 + or IsShiftKeyDown() and v.modifier == 3 then + name = v.name + break + end + end + + if isLeftButton or isRightButton then + display:DisplayInterface(name) + else + EasyMenu(menu, dropdown, frame, 0, 0, "MENU") + end +end + +function addon:IsMenuVisible() + local current = UIDropDownMenu_GetCurrentDropDown() + if current and current == dropdown and DropDownList1:IsShown() then + return true + else + return false + end +end \ No newline at end of file diff --git a/Options.lua b/Options.lua deleted file mode 100644 index 0cb7f39..0000000 --- a/Options.lua +++ /dev/null @@ -1,250 +0,0 @@ ---[[ - Copyright (c) 2014 Eyal Shilony - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -]] - -local addonName, addon = ... -local display = LibStub("EasyDisplay-1.0") -local L = LibStub("AceLocale-3.0"):GetLocale(addonName) - -function addon:InitializeOptions() - local options = { - name = addon.name, - type = "group", - args = { - { - type = "description", - name = function() - return GetAddOnMetadata(addonName, "Notes") - end, - cmdHidden = true, - }, - { - type = "header", - name = "", - }, - { - type = "description", - name = "", - }, - { - type = "toggle", - name = L["Block the menu in combat"], - get = function() - return addon.db.profile.blockInCombat - end, - set = function() - addon.db.profile.blockInCombat = not addon.db.profile.blockInCombat - end, - width = "full", - }, - { - type = "toggle", - name = L["Hide the logout and exit items from the menu"], - get = function() - return addon.db.profile.hideLogoutButtons - end, - set = function() - addon.db.profile.hideLogoutButtons = not addon.db.profile.hideLogoutButtons - addon.updateMenu = true - end, - width = "full", - }, - { - type = "toggle", - name = L["Hide the reload item from the menu"], - get = function() - return addon.db.profile.hideReloadUIButton - end, - set = function() - addon.db.profile.hideReloadUIButton = not addon.db.profile.hideReloadUIButton - addon.updateMenu = true - end, - width = "full", - }, - { - type = "toggle", - name = L["Hide the options item from the menu"], - get = function() - return addon.db.profile.hideOptionsButton - end, - set = function() - addon.db.profile.hideOptionsButton = not addon.db.profile.hideOptionsButton - addon.updateMenu = true - end, - width = "full", - }, - { - type = "header", - name = L["Tooltip"], - }, - { - type = "description", - name = "", - }, - { - type = "toggle", - name = L["Hide tooltip"], - get = function() - return addon.db.profile.hideTooltip - end, - set = function() - addon.db.profile.hideTooltip = not addon.db.profile.hideTooltip - end, - width = "full", - }, - { - type = "range", - name = L["Number of addons to display"], - get = function() - return addon.db.profile.numAddOns - end, - set = function(_, value) - addon.db.profile.numAddOns = value - end, - step = 1, - min = 1, - max = 40, - width = "full", - }, - }, - } - addon:RegisterOptions(options) - - local accessibility = { - name = L["Accessibility"], - type = "group", - args = { - { - type = "description", - name = L["Bind up to four menu items to the mouse which you can use to open them quickly by clicking on the broker display."], - cmdHidden = true, - }, - { - type = "header", - name = "", - }, - { - type = "select", - name = L["Mouse Setting"], - get = function() - return addon.db.profile.mouseButton - end, - set = function(_, value) - addon.db.profile.mouseButton = value - end, - values = addon.buttons, - }, - { - type = "header", - name = "", - }, - }, - } - - local num = 0 - local titles = { } - for _, v in display:Interfaces() do - num = num + 1 - table.insert(titles, v.title) - end - - for i, v in pairs(addon.db.profile.accessibility) do - table.insert(accessibility.args, { - type = "select", - name = L["Action %s"]:format(i), - get = function() - local _, index = display:GetInterface(addon.db.profile.accessibility[i].name) - return index - end, - set = function(_, value) - local interface = display:GetInterfaceByIndex(value) - addon.db.profile.accessibility[i].name = interface.name - end, - values = titles, - width = "double", - }) - table.insert(accessibility.args, { - type = "select", - name = L["Modifier"], - get = function() - return addon.db.profile.accessibility[i].modifier - end, - set = function(_, value) - addon.db.profile.accessibility[i].modifier = value - end, - values = addon.modifiers, - }) - end - table.insert(accessibility.args, { - type = "header", - name = "", - }) - table.insert(accessibility.args, { - type = "toggle", - name = L["Hide the bindings from the tooltip"], - get = function() - return addon.db.profile.hideTooltipAccessibilityBindings - end, - set = function() - addon.db.profile.hideTooltipAccessibilityBindings = not addon.db.profile.hideTooltipAccessibilityBindings - end, - width = "full", - }) - addon:RegisterOptions(accessibility) - - local order = { - name = L["Order"] , - type = "group", - args = { - { - type = "description", - name = L["Sort the order of the menu items.\n\nNote, having no sorting order (zero) hides the item from the menu."], - cmdHidden = true, - }, - { - type = "header", - name = "", - }, - }, - } - - for _, v in display:Interfaces() do - table.insert(order.args, { - type = "range", - name = v.title, - get = function() - return addon.db.profile.order[v.name] - end, - set = function(_, value) - addon.db.profile.order[v.name] = value - addon.updateMenu = true - end, - step = 1, - min = 0, - max = num, - width = "full", - }) - end - addon:RegisterOptions(order) - - addon:RegisterOptions(LibStub("AceDBOptions-3.0"):GetOptionsTable(addon.db), true) -end \ No newline at end of file diff --git a/SecureButtonsOverlay.lua b/SecureButtonsOverlay.lua deleted file mode 100644 index c978f9e..0000000 --- a/SecureButtonsOverlay.lua +++ /dev/null @@ -1,111 +0,0 @@ ---[[ - Copyright (c) 2014 Eyal Shilony - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -]] - -local _, addon = ... - -local secureButtons = { } - --- script handlers to mimic regular dropdown button behaviour --- close menu when clicked -local function onClick(self) - self.parent:GetParent():Hide() -end - -local function onMouseDown(self) - self.parent:SetButtonState("PUSHED") -end - -local function onMouseUp(self) - self.parent:SetButtonState("NORMAL") -end - --- prevent menu from hiding -local function onEnter(self) - local grandParent = self.parent:GetParent() - CloseDropDownMenus(grandParent:GetID() + 1) - _G[self.parent:GetName().."Highlight"]:Show() - UIDropDownMenu_StopCounting(grandParent) -end - --- hide menu after timeout -local function onLeave(self) - _G[self.parent:GetName().."Highlight"]:Hide() - UIDropDownMenu_StartCounting(self.parent:GetParent()) - GameTooltip:Hide() -end - -local function createSecureButtonOverlay(button) - local secureButton = CreateFrame("Button", nil, nil, "SecureActionButtonTemplate") - secureButton:SetSize(200, 16) - secureButton:HookScript("OnClick", onClick) - secureButton:SetScript("OnEnter", onEnter) - secureButton:SetScript("OnLeave", onLeave) - secureButton:SetScript("OnMouseDown", onMouseDown) - secureButton:SetScript("OnMouseUp", onMouseUp) - secureButton:SetAttribute("type", "click") - secureButton:SetAttribute("clickbutton", button) - return secureButton -end - --- TODO: We can remove the dependency on the menu by using the dropdown itself, for now it works! -function addon:AddSecureButtonsOverlay(menu) - local index = 0 - for _, item in pairs(menu) do - if item.order and item.order > 0 then - index = index + 1 - local parent = _G["DropDownList1Button" .. index] - if not parent then - UIDropDownMenu_CreateFrames(1, index) - parent = _G["DropDownList1Button" .. index] - end - if parent and item.button then - local button = createSecureButtonOverlay(item.button) - table.insert(secureButtons, button) - button.parent = parent - button:SetParent(parent) - button:SetAllPoints() - --[[button:SetBackdrop({ - bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", - tile = true, - tileSize = 16, - --edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", - edgeSize = 16, - insets = {left = 5, right = 3, top = 3, bottom = 5} - }) - button:SetBackdropColor(0, 1, 0, 0.5)]] - button:Show() - end - end - end -end - -function addon:RemoveSecureButtonsOverlay() - if #secureButtons > 0 then - for index, button in ipairs(secureButtons) do - button:SetParent(UIParent) - button:ClearAllPoints() - button:Hide() - end - wipe(secureButtons) - end -end \ No newline at end of file diff --git a/Tooltip.lua b/Tooltip.lua new file mode 100644 index 0000000..4d836a8 --- /dev/null +++ b/Tooltip.lua @@ -0,0 +1,202 @@ +--[[ + Copyright (c) 2014 Eyal Shilony + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +]] + +local addonName, addon = ... +local display = LibStub("EasyDisplay-1.0") +local L = LibStub("AceLocale-3.0"):GetLocale(addonName) + +local function addons() + local n = 1 + local count = 0 + local max = 40 + local addons = GetNumAddOns() + return function () + for i = n, addons do + local name, _, _, enabled = GetAddOnInfo(i) + if count <= max and enabled then + n = i + 1 + count = count + 1 + return name, GetAddOnMemoryUsage(i) + end + end + end +end + +local function getTotalMemUsage() + UpdateAddOnMemoryUsage() + + local long, short + local totalMem = 0 + + for _, mem in addons() do + totalMem = totalMem + mem + end + + if totalMem > 0 then + if totalMem > 1000 then + totalMem = totalMem / 1000 + short = format("%.2f MB", totalMem) + long = format(TOTAL_MEM_MB_ABBR, totalMem) + else + short = format("%.0f KB", totalMem) + long = format(TOTAL_MEM_KB_ABBR, totalMem) + end + end + + return totalMem, long, short +end + +local topAddOns = { } +local numAddOns = 0 +local tooltip = GameTooltip + +function addon:UpdateTooltip() + local db = self.db.profile + + if db.hideTooltip then + return + end + + if numAddOns ~= db.numAddOns then + for i=1, db.numAddOns do + topAddOns[i] = { value = 0, name = "" } + end + numAddOns = db.numAddOns + end + + local text = "" + local i, j, k = 0, 0, 0 + + tooltip:ClearLines() + + tooltip:AddLine(self.name, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + + -- latency + local _, _, latencyHome, latencyWorld = GetNetStats() + text = format(MAINMENUBAR_LATENCY_LABEL, latencyHome, latencyWorld) + tooltip:AddLine(" ") + tooltip:AddLine(text, 1.0, 1.0, 1.0) + if SHOW_NEWBIE_TIPS == "1" then + tooltip:AddLine(NEWBIE_TOOLTIP_LATENCY, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + end + tooltip:AddLine(" ") + + -- framerate + text = format(MAINMENUBAR_FPS_LABEL, GetFramerate()) + tooltip:AddLine(text, 1.0, 1.0, 1.0) + if SHOW_NEWBIE_TIPS == "1" then + tooltip:AddLine(NEWBIE_TOOLTIP_FRAMERATE, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + end + + local bandwidth = GetAvailableBandwidth() + if not bandwidth == 0 then + tooltip:AddLine(" ") + text = format(MAINMENUBAR_BANDWIDTH_LABEL, GetAvailableBandwidth()) + tooltip:AddLine(text, 1.0, 1.0, 1.0) + if SHOW_NEWBIE_TIPS == "1" then + tooltip:AddLine(NEWBIE_TOOLTIP_BANDWIDTH, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + end + end + + local percent = floor(GetDownloadedPercentage() * 100 + 0.5) + if not percent == 0 then + tooltip:AddLine(" ") + text = format(MAINMENUBAR_DOWNLOAD_PERCENT_LABEL, percent) + tooltip:AddLine(text, 1.0, 1.0, 1.0) + if ( SHOW_NEWBIE_TIPS == "1" ) then + tooltip:AddLine(NEWBIE_TOOLTIP_DOWNLOAD_PERCENT, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + end + end + + -- memory + local totalMem, totalText = getTotalMemUsage() + + if totalMem > 0 then + local mem + + for i = 1, db.numAddOns, 1 do + topAddOns[i].value = 0 + end + + for name, mem in addons() do + for j = 1, db.numAddOns, 1 do + if mem > topAddOns[j].value then + for k = db.numAddOns, 1, -1 do + if k == j then + topAddOns[k].value = mem + topAddOns[k].name = name + break + elseif k ~= 1 then + topAddOns[k].value = topAddOns[k-1].value + topAddOns[k].name = topAddOns[k-1].name + end + end + break + end + end + end + + tooltip:AddLine(" ") + tooltip:AddLine(totalText, 1.0, 1.0, 1.0) + if SHOW_NEWBIE_TIPS == "1" then + tooltip:AddLine(NEWBIE_TOOLTIP_MEMORY, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) + end + + for i = 1, db.numAddOns, 1 do + if topAddOns[i].value == 0 then + break + end + + local size = topAddOns[i].value + + if size > 1000 then + size = size / 1000 + text = format(ADDON_MEM_MB_ABBR, size, topAddOns[i].name) + else + text = format(ADDON_MEM_KB_ABBR, size, topAddOns[i].name) + end + + tooltip:AddLine(text, 1.0, 1.0, 1.0) + end + end + + -- accessibility + if not db.hideTooltipAccessibilityBindings then + tooltip:AddLine(" ") + + local text = "" + + for i, v in ipairs(db.accessibility) do + local mouseButton = addon.buttons[db.mouseButton] + if v.modifier == 4 then + text = ": |cffffffff" .. mouseButton .. "|r" + else + text = ": |cffffffff" .. mouseButton .. " + " .. addon.modifiers[v.modifier] .. "|r" + end + text = display:GetInterface(v.name).title .. text + tooltip:AddLine(text, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b) + end + end + + tooltip:Show() +end \ No newline at end of file diff --git a/libs/AceConfig-3.0/AceConfig-3.0.lua b/libs/AceConfig-3.0/AceConfig-3.0.lua deleted file mode 100644 index 3bedf8c..0000000 --- a/libs/AceConfig-3.0/AceConfig-3.0.lua +++ /dev/null @@ -1,57 +0,0 @@ ---- 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 diff --git a/libs/AceConfig-3.0/AceConfig-3.0.xml b/libs/AceConfig-3.0/AceConfig-3.0.xml deleted file mode 100644 index 87972ad..0000000 --- a/libs/AceConfig-3.0/AceConfig-3.0.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -