local Postal = LibStub("AceAddon-3.0"):NewAddon("Postal", "AceEvent-3.0", "AceHook-3.0") local L = LibStub("AceLocale-3.0"):GetLocale("Postal") _G["Postal"] = Postal -- defaults for storage local defaults = { profile = { ModuleEnabledState = { ["*"] = true }, OpenSpeed = 0.50, ChatOutput = 1, Select = { SpamChat = true, KeepFreeSpace = 1, }, OpenAll = { AHCancelled = true, AHExpired = true, AHOutbid = true, AHSuccess = true, AHWon = true, NeutralAHCancelled = true, NeutralAHExpired = true, NeutralAHOutbid = true, NeutralAHSuccess = true, NeutralAHWon = true, Postmaster = true, Attachments = true, SpamChat = true, KeepFreeSpace = 1, }, Express = { EnableAltClick = true, AutoSend = true, BulkSend = true, MouseWheel = true, MultiItemTooltip = true, }, BlackBook = { AutoFill = true, contacts = {}, recent = {}, AutoCompleteAlts = true, AutoCompleteAllAlts = true, AutoCompleteRecent = true, AutoCompleteContacts = true, AutoCompleteFriends = true, AutoCompleteGuild = true, ExcludeRandoms = true, DisableBlizzardAutoComplete = false, UseAutoComplete = true, }, }, global = { BlackBook = { alts = {}, }, }, } local _G = getfenv(0) local t = {} Postal.keepFreeOptions = {0, 1, 2, 3, 5, 10, 15, 20, 25, 30} -- Use a common frame and setup some common functions for the Postal dropdown menus local Postal_DropDownMenu = CreateFrame("Frame", "Postal_DropDownMenu") Postal_DropDownMenu.displayMode = "MENU" Postal_DropDownMenu.info = {} Postal_DropDownMenu.levelAdjust = 0 Postal_DropDownMenu.UncheckHack = function(dropdownbutton) _G[dropdownbutton:GetName().."Check"]:Hide() _G[dropdownbutton:GetName().."UnCheck"]:Hide() end Postal_DropDownMenu.HideMenu = function() if UIDROPDOWNMENU_OPEN_MENU == Postal_DropDownMenu then CloseDropDownMenus() end end -- Functions for long subject mouseover local function subjectHoverIn(self) local s = _G["MailItem"..self:GetID().."Subject"] if s:GetStringWidth() + 25 > s:GetWidth() then GameTooltip:SetOwner(self, "ANCHOR_RIGHT") GameTooltip:SetText(s:GetText()) GameTooltip:Show() end end local function subjectHoverOut(self) GameTooltip:Hide() end --------------------------- -- Postal Core Functions -- --------------------------- function Postal:OnInitialize() -- Version number if not self.version then self.version = GetAddOnMetadata("Postal", "Version") end -- Initialize database self.db = LibStub("AceDB-3.0"):New("Postal3DB", defaults) self.db.RegisterCallback(self, "OnProfileChanged", "OnProfileChanged") self.db.RegisterCallback(self, "OnProfileCopied", "OnProfileChanged") self.db.RegisterCallback(self, "OnProfileReset", "OnProfileChanged") -- Enable/disable modules based on saved settings for name, module in self:IterateModules() do module:SetEnabledState(self.db.profile.ModuleEnabledState[name] or false) if module.OnEnable then hooksecurefunc(module, "OnEnable", self.OnModuleEnable_Common) -- Posthook end end -- Register events self:RegisterEvent("MAIL_CLOSED") -- Create the Menu Button local Postal_ModuleMenuButton = CreateFrame("Button", "Postal_ModuleMenuButton", MailFrame) Postal_ModuleMenuButton:SetWidth(25) Postal_ModuleMenuButton:SetHeight(25) Postal_ModuleMenuButton:SetPoint("TOPRIGHT", -22, 2) Postal_ModuleMenuButton:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Up") Postal_ModuleMenuButton:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Round") Postal_ModuleMenuButton:SetDisabledTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Disabled") Postal_ModuleMenuButton:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Down") Postal_ModuleMenuButton:SetScript("OnClick", function(self, button, down) if Postal_DropDownMenu.initialize ~= Postal.Menu then CloseDropDownMenus() Postal_DropDownMenu.initialize = Postal.Menu end ToggleDropDownMenu(1, nil, Postal_DropDownMenu, self:GetName(), 0, 0) end) Postal_ModuleMenuButton:SetScript("OnHide", Postal_DropDownMenu.HideMenu) -- Create 7 buttons for mouseover on long subject lines for i = 1, 7 do local b = CreateFrame("Button", "PostalSubjectHover"..i, _G["MailItem"..i]) b:SetID(i) b:SetAllPoints(_G["MailItem"..i.."Subject"]) b:SetScript("OnEnter", subjectHoverIn) b:SetScript("OnLeave", subjectHoverOut) end self.OnInitialize = nil end function Postal:OnProfileChanged(event, database, newProfileKey) for name, module in self:IterateModules() do if self.db.profile.ModuleEnabledState[name] then module:Enable() else module:Disable() end end end function Postal:OnModuleEnable_Common() -- If the module is enabled with the MailFrame open (at mailbox) -- run the MAIL_SHOW() event function if self.MAIL_SHOW and MailFrame:IsVisible() then self:MAIL_SHOW() end end -- Hides the minimap unread mail button if there are no unread mail on closing the mailbox. -- Does not scan past the first 50 items since only the first 50 are viewable. function Postal:MAIL_CLOSED() for i = 1, GetInboxNumItems() do if not select(9, GetInboxHeaderInfo(i)) then return end end MiniMapMailFrame:Hide() end function Postal:Print(...) local text = "|cff33ff99Postal|r:" for i = 1, select("#", ...) do text = text.." "..tostring(select(i, ...)) end if not self:IsChatFrameActive(self.db.profile.ChatOutput) then self.db.profile.ChatOutput = 1 end local chatFrame = _G["ChatFrame"..self.db.profile.ChatOutput] if chatFrame then chatFrame:AddMessage(text) end end function Postal:IsChatFrameActive(i) local _, _, _, _, _, _, shown = FCF_GetChatWindowInfo(i); local chatFrame = _G["ChatFrame"..i] if chatFrame then if shown or chatFrame.isDocked then return true end end return false end function Postal.SaveOption(dropdownbutton, arg1, arg2, checked) Postal.db.profile[arg1][arg2] = checked end function Postal.ToggleModule(dropdownbutton, arg1, arg2, checked) Postal.db.profile.ModuleEnabledState[arg1] = checked if checked then arg2:Enable() else arg2:Disable() end end function Postal.SetOpenSpeed(dropdownbutton, arg1, arg2, checked) Postal.db.profile.OpenSpeed = arg1 end function Postal.SetChatOutput(dropdownbutton, arg1, arg2, checked) Postal.db.profile.ChatOutput = arg1 end function Postal.ProfileFunc(dropdownbutton, arg1, arg2, checked) if arg1 == "NewProfile" then StaticPopup_Show("POSTAL_NEW_PROFILE") else Postal.db[arg1](Postal.db, arg2) end CloseDropDownMenus() end StaticPopupDialogs["POSTAL_NEW_PROFILE"] = { text = L["New Profile Name:"], button1 = ACCEPT, button2 = CANCEL, hasEditBox = 1, maxLetters = 128, editBoxWidth = 350, -- Needed in Cata OnAccept = function(self) Postal.db:SetProfile(strtrim(self.editBox:GetText())) end, OnShow = function(self) self.editBox:SetText(Postal.db:GetCurrentProfile()) self.editBox:SetFocus() end, OnHide = StaticPopupDialogs["SET_GUILDPLAYERNOTE"].OnHide, EditBoxOnEnterPressed = function(self) local parent = self:GetParent() Postal.db:SetProfile(strtrim(parent.editBox:GetText())) parent:Hide() end, EditBoxOnEscapePressed = StaticPopupDialogs["SET_GUILDPLAYERNOTE"].EditBoxOnEscapePressed, timeout = 0, exclusive = 1, whileDead = 1, hideOnEscape = 1 } function Postal.Menu(self, level) if not level then return end local info = self.info wipe(info) if level == 1 then info.isTitle = 1 info.text = "Postal" info.notCheckable = 1 UIDropDownMenu_AddButton(info, level) info.disabled = nil info.isTitle = nil info.notCheckable = nil info.keepShownOnClick = 1 info.isNotRadio = 1 for name, module in Postal:IterateModules() do info.text = L[name] info.func = Postal.ToggleModule info.arg1 = name info.arg2 = module info.checked = module:IsEnabled() info.hasArrow = module.ModuleMenu ~= nil info.value = module UIDropDownMenu_AddButton(info, level) end wipe(info) info.disabled = 1 UIDropDownMenu_AddButton(info, level) info.disabled = nil info.text = L["Opening Speed"] info.func = self.UncheckHack info.notCheckable = 1 info.keepShownOnClick = 1 info.hasArrow = 1 info.value = "OpenSpeed" UIDropDownMenu_AddButton(info, level) info.text = L["Chat Output"] info.func = self.UncheckHack info.notCheckable = 1 info.keepShownOnClick = 1 info.hasArrow = 1 info.value = "ChatOutput" UIDropDownMenu_AddButton(info, level) info.text = L["Profile"] info.func = self.UncheckHack info.value = "Profile" UIDropDownMenu_AddButton(info, level) wipe(info) info.notCheckable = 1 info.text = L["Help"] info.func = Postal.About UIDropDownMenu_AddButton(info, level) info.disabled = 1 info.text = nil info.func = nil UIDropDownMenu_AddButton(info, level) info.disabled = nil info.text = CLOSE info.func = self.HideMenu info.tooltipTitle = CLOSE UIDropDownMenu_AddButton(info, level) elseif level == 2 then if UIDROPDOWNMENU_MENU_VALUE == "OpenSpeed" then local speed = Postal.db.profile.OpenSpeed for i = 0, 13 do local s = 0.3 + i*0.05 info.text = format("%0.2f", s) info.func = Postal.SetOpenSpeed info.checked = s == speed info.arg1 = s UIDropDownMenu_AddButton(info, level) end for i = 0, 8 do local s = 1 + i*0.5 info.text = format("%0.2f", s) info.func = Postal.SetOpenSpeed info.checked = s == speed info.arg1 = s UIDropDownMenu_AddButton(info, level) end elseif UIDROPDOWNMENU_MENU_VALUE == "ChatOutput" then local selectedFrame = Postal.db.profile.ChatOutput for i = 1, NUM_CHAT_WINDOWS do if Postal:IsChatFrameActive(i) then info.text = format("%d. %s", i, _G["ChatFrame"..i.."Tab"]:GetText()) info.func = Postal.SetChatOutput info.checked = i == selectedFrame info.arg1 = i UIDropDownMenu_AddButton(info, level) end end elseif UIDROPDOWNMENU_MENU_VALUE == "Profile" then -- Profile stuff info.hasArrow = 1 info.keepShownOnClick = 1 info.func = self.UncheckHack info.notCheckable = 1 info.text = L["Choose"] info.value = "SetProfile" UIDropDownMenu_AddButton(info, level) info.text = L["Copy From"] info.value = "CopyProfile" UIDropDownMenu_AddButton(info, level) info.text = L["Delete"] info.value = "DeleteProfile" UIDropDownMenu_AddButton(info, level) info.hasArrow = nil info.keepShownOnClick = nil info.func = Postal.ProfileFunc info.arg1 = "NewProfile" info.text = L["New Profile"] UIDropDownMenu_AddButton(info, level) info.text = L["Reset Profile"] info.func = Postal.ProfileFunc info.arg1 = "ResetProfile" info.arg2 = nil UIDropDownMenu_AddButton(info, level) elseif type(UIDROPDOWNMENU_MENU_VALUE) == "table" and UIDROPDOWNMENU_MENU_VALUE.ModuleMenu then -- Submenus for modules self.levelAdjust = 1 UIDROPDOWNMENU_MENU_VALUE.ModuleMenu(self, level) self.levelAdjust = 0 self.module = UIDROPDOWNMENU_MENU_VALUE end elseif level == 3 then if UIDROPDOWNMENU_MENU_VALUE == "SetProfile" then local cur = Postal.db:GetCurrentProfile() Postal.db:GetProfiles(t) table.sort(t) info.func = Postal.ProfileFunc info.arg1 = "SetProfile" for i = 1, #t do local s = t[i] info.text = s info.arg2 = s info.checked = cur == s UIDropDownMenu_AddButton(info, level) end elseif UIDROPDOWNMENU_MENU_VALUE == "CopyProfile" or UIDROPDOWNMENU_MENU_VALUE == "DeleteProfile" then local cur = Postal.db:GetCurrentProfile() Postal.db:GetProfiles(t) table.sort(t) info.func = Postal.ProfileFunc info.arg1 = UIDROPDOWNMENU_MENU_VALUE info.notCheckable = 1 for i = 1, #t do local s = t[i] if s ~= cur then info.text = s info.arg2 = s UIDropDownMenu_AddButton(info, level) end end elseif self.module and self.module.ModuleMenu then self.levelAdjust = 1 self.module.ModuleMenu(self, level) self.levelAdjust = 0 end elseif level > 3 then if self.module and self.module.ModuleMenu then self.levelAdjust = 1 self.module.ModuleMenu(self, level) self.levelAdjust = 0 end end end function Postal:CreateAboutFrame() local aboutFrame = Postal.aboutFrame if not aboutFrame and Chatter and ChatterCopyFrame then aboutFrame = ChatterCopyFrame aboutFrame.editBox = Chatter:GetModule("Chat Copy").editBox end if not aboutFrame or not aboutFrame.editBox then aboutFrame = CreateFrame("Frame", "PostalAboutFrame", UIParent) tinsert(UISpecialFrames, "PostalAboutFrame") aboutFrame:SetBackdrop({ bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]], edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]], tile = true, tileSize = 16, edgeSize = 16, insets = { left = 3, right = 3, top = 5, bottom = 3 } }) aboutFrame:SetBackdropColor(0,0,0,1) aboutFrame:SetWidth(500) aboutFrame:SetHeight(400) aboutFrame:SetPoint("CENTER", UIParent, "CENTER") aboutFrame:Hide() aboutFrame:SetFrameStrata("DIALOG") aboutFrame:SetToplevel(true) local scrollArea = CreateFrame("ScrollFrame", "PostalAboutScroll", aboutFrame, "UIPanelScrollFrameTemplate") scrollArea:SetPoint("TOPLEFT", aboutFrame, "TOPLEFT", 8, -30) scrollArea:SetPoint("BOTTOMRIGHT", aboutFrame, "BOTTOMRIGHT", -30, 8) local editBox = CreateFrame("EditBox", nil, aboutFrame) editBox:SetMultiLine(true) editBox:SetMaxLetters(99999) editBox:EnableMouse(true) editBox:SetAutoFocus(false) editBox:SetFontObject(ChatFontNormal) editBox:SetWidth(400) editBox:SetHeight(270) editBox:SetScript("OnEscapePressed", function() aboutFrame:Hide() end) aboutFrame.editBox = editBox scrollArea:SetScrollChild(editBox) local close = CreateFrame("Button", nil, aboutFrame, "UIPanelCloseButton") close:SetPoint("TOPRIGHT", aboutFrame, "TOPRIGHT") end Postal.aboutFrame = aboutFrame Postal.CreateAboutFrame = nil -- Kill ourselves end function Postal.About() if Postal.CreateAboutFrame then Postal:CreateAboutFrame() end local version = GetAddOnMetadata("Postal", "Version") wipe(t) tinsert(t, "|cFFFFCC00"..GetAddOnMetadata("Postal", "Title").." v"..version.."|r") tinsert(t, "-----") tinsert(t, "") for name, module in Postal:IterateModules() do tinsert(t, "|cffffcc00"..L[name].."|r") if module.description then tinsert(t, module.description) end if module.description2 then tinsert(t, "") tinsert(t, module.description2) end tinsert(t, "") end tinsert(t, "-----") tinsert(t, L["Please post bugs or suggestions at the wowace forums thread at |cFF00FFFFhttp://forums.wowace.com/showthread.php?t=3909|r. When posting bugs, indicate your locale and Postal's version number v%s."]:format(version)) tinsert(t, "") tinsert(t, "- Xinhuan (Blackrock/Barthilas US Alliance)") tinsert(t, "") Postal.aboutFrame.editBox:SetText(table.concat(t, "\n")) Postal.aboutFrame:Show() wipe(t) -- For garbage collection end --------------------------- -- Common Mail Functions -- --------------------------- -- Disable Inbox Clicks local function noop() end function Postal:DisableInbox(disable) if disable then if not self:IsHooked("InboxFrame_OnClick") then self:RawHook("InboxFrame_OnClick", noop, true) for i = 1, 7 do _G["MailItem" .. i .. "ButtonIcon"]:SetDesaturated(true) end end else if self:IsHooked("InboxFrame_OnClick") then self:Unhook("InboxFrame_OnClick") for i = 1, 7 do _G["MailItem" .. i .. "ButtonIcon"]:SetDesaturated(false) end end end end -- Return the type of mail a message subject is local SubjectPatterns = { AHCancelled = gsub(AUCTION_REMOVED_MAIL_SUBJECT, "%%s", ".*"), AHExpired = gsub(AUCTION_EXPIRED_MAIL_SUBJECT, "%%s", ".*"), AHOutbid = gsub(AUCTION_OUTBID_MAIL_SUBJECT, "%%s", ".*"), AHSuccess = gsub(AUCTION_SOLD_MAIL_SUBJECT, "%%s", ".*"), AHWon = gsub(AUCTION_WON_MAIL_SUBJECT, "%%s", ".*"), } function Postal:GetMailType(msgSubject) if msgSubject then for k, v in pairs(SubjectPatterns) do if msgSubject:find(v) then return k end end end return "NonAHMail" end function Postal:GetMoneyString(money) local gold = floor(money / 10000) local silver = floor((money - gold * 10000) / 100) local copper = mod(money, 100) if gold > 0 then return format(GOLD_AMOUNT_TEXTURE.." "..SILVER_AMOUNT_TEXTURE.." "..COPPER_AMOUNT_TEXTURE, gold, 0, 0, silver, 0, 0, copper, 0, 0) elseif silver > 0 then return format(SILVER_AMOUNT_TEXTURE.." "..COPPER_AMOUNT_TEXTURE, silver, 0, 0, copper, 0, 0) else return format(COPPER_AMOUNT_TEXTURE, copper, 0, 0) end end function Postal:GetMoneyStringPlain(money) local gold = floor(money / 10000) local silver = floor((money - gold * 10000) / 100) local copper = mod(money, 100) if gold > 0 then return gold..GOLD_AMOUNT_SYMBOL.." "..silver..SILVER_AMOUNT_SYMBOL.." "..copper..COPPER_AMOUNT_SYMBOL elseif silver > 0 then return silver..SILVER_AMOUNT_SYMBOL.." "..copper..COPPER_AMOUNT_SYMBOL else return copper..COPPER_AMOUNT_SYMBOL end end function Postal:CountItemsAndMoney() local numAttach = 0 local numGold = 0 for i = 1, GetInboxNumItems() do local msgMoney, _, _, msgItem = select(5, GetInboxHeaderInfo(i)) numAttach = numAttach + (msgItem or 0) numGold = numGold + msgMoney end return numAttach, numGold end