Share Pastebin
Guest
Public paste!

Untitled

By: a guest | Mar 20th, 2010 | Syntax: None | Size: 41.52 KB | Hits: 24 | Expires: Never
Copy text to clipboard
  1. Cartographer = Rock:NewAddon("Cartographer", "LibRockConsole-1.0", "LibRockEvent-1.0", "LibRockTimer-1.0", "LibRockDB-1.0", "LibRockModuleCore-1.0", "LibRockHook-1.0", "LibRockConfig-1.0")
  2. local Cartographer = Cartographer
  3. Cartographer.revision = tonumber(string.sub("$Revision: 2320 $", 12, -3))
  4. Cartographer.version = "r" .. Cartographer.revision
  5. Cartographer.date = string.sub("$Date: 2009-04-17 00:45:12 +0000 (Fri, 17 Apr 2009) $", 8, 17)
  6. Cartographer:SetDatabase("CartographerDB")
  7.  
  8. local Dewdrop = AceLibrary("Dewdrop-2.0")
  9.  
  10. local L = Rock("LibRockLocale-1.0"):GetTranslationNamespace("Cartographer")
  11. Cartographer.L = L
  12. local Crayon = Rock("LibCrayon-3.0")
  13. local BZ = Rock("LibBabble-Zone-3.0")
  14. local BZL = BZ:GetLookupTable()
  15. local BZH = BZ:GetUnstrictLookupTable()
  16. local BZR = BZ:GetReverseLookupTable()
  17. local Tablet = AceLibrary("Tablet-2.0")
  18. local Tourist = Rock("LibTourist-3.0")
  19. local LibGuild = Rock("LibGuild-1.0")
  20. local AceEvent
  21. local precondition, argCheck = Rock:GetContractFunctions("Cartographer", "precondition", "argCheck")
  22.  
  23. do
  24.         -- hack, but Blizz is weird
  25.         if WorldMapButton:GetScript("OnMouseUp") == WorldMapButton_OnClick then
  26.                 WorldMapButton:SetScript("OnMouseUp", function(self, ...)
  27.                         WorldMapButton_OnClick(self, ...)
  28.                 end)
  29.         end
  30.         if WorldMapButton:GetScript("OnUpdate") == WorldMapButton_OnUpdate then
  31.                 WorldMapButton:SetScript("OnUpdate", function(self, ...)
  32.                         WorldMapButton_OnUpdate(self, ...)
  33.                 end)
  34.         end
  35. end
  36.  
  37. L:AddTranslations("enUS", function() return {
  38.         ["Active"] = "Enabled", -- remove in a while (2006-12-08)
  39.         ["Enabled"] = true,
  40.         ["Suspend/resume this module."] = true,
  41.  
  42.         ["Right-Click on map to zoom out"] = true,
  43.         ["Left-Click on map to zoom in"] = true,
  44.  
  45.         ["Go to %s"] = true,
  46.  
  47.         ["Open Cartographer menu"] = true,
  48.         ["Open location menu"] = true,
  49.  
  50.         ["Distance:"] = true,
  51.  
  52.         ["Close information pane"] = true,
  53.         ["Close this side informational pane"] = true,
  54.  
  55.         ["Zones"] = true,
  56.         ["Cities"] = true,
  57.  
  58.         ["%.0f yd"] = true,
  59.         ["%.0f m"] = true,
  60.         ["Cartographer"] = true,
  61.         ["Open alternate map"] = true,
  62.  
  63.         ["Addon to manipulate the map."] = true,
  64. } end)
  65.  
  66. L:AddTranslations("deDE", function() return {
  67.         ["Enabled"] = "Aktiviert",
  68.         ["Suspend/resume this module."] = "Aktiviert/Deaktiviert dieses Modul",
  69.  
  70.         ["Right-Click on map to zoom out"] = "Rechtsklick auf die Karte verkleinert die Ansicht",
  71.         ["Left-Click on map to zoom in"] = "Linksklick auf die Karte vergr\195\182\195\159ert die Ansicht",
  72.  
  73.         ["Go to %s"] = "Gehe zu %s",
  74.  
  75.         ["Open Cartographer menu"] = "Cartographer-Men\195\188 \195\182ffnen",
  76.         ["Open location menu"] = "Positionsmen\195\188 \195\182ffnen",
  77.  
  78.         ["Distance:"] = "Distanz:",
  79.  
  80.         ["Close information pane"] = "Informationsfeld schlie\195\159en",
  81.         ["Close this side informational pane"] = "Das seitliche Informationsfeld schlie\195\159en",
  82.  
  83.         ["Zones"] = "Zonen",
  84.         ["Cities"] = "St\195\164dte",
  85. } end)
  86.  
  87. L:AddTranslations("frFR", function() return {
  88.         ["Active"] = "Activé",
  89.         ["Enabled"] = "Activé",
  90.         ["Suspend/resume this module."] = "Active ou non ce module.",
  91.  
  92.         ["Right-Click on map to zoom out"] = "Clic-droit sur la carte pour effectuer un zoom arrière",
  93.         ["Left-Click on map to zoom in"] = "Clic-gauche sur la carte pour effectuer un zoom avant",
  94.  
  95.         ["Go to %s"] = "Allez à %s",
  96.  
  97.         ["Open Cartographer menu"] = "Ouvrir le menu Cartographer",
  98.         ["Open location menu"] = "Ouvrir le menu de situation",
  99.  
  100.         ["Distance:"] = "Distance:",
  101.  
  102.         ["Close information pane"] = "Fermer le panneau d'information",
  103.         ["Close this side informational pane"] = "Ferme ce panneau latéral d'information.",
  104.  
  105.         ["Zones"] = "Zones",
  106.         ["Cities"] = "Capitales",
  107.  
  108.         ["Addon to manipulate the map."] = "Addon de manipulation de la carte.",
  109. } end)
  110.  
  111. L:AddTranslations("koKR", function() return {
  112.         ["Active"] = "사용",
  113.         ["Enabled"] = "사용중",
  114.         ["Suspend/resume this module."] = "현재 모듈을 사용하거나 중지합니다.",
  115.  
  116.         ["Right-Click on map to zoom out"] = "우-클릭 : 축소",
  117.         ["Left-Click on map to zoom in"] = "좌-클릭 : 확대",
  118.  
  119.         ["Go to %s"] = "%s 바로가기",
  120.  
  121.         ["Open Cartographer menu"] = "Cartographer 메뉴 열기",
  122.         ["Open location menu"] = "위치 메뉴 열기",
  123.  
  124.         ["Distance:"] = "거리:",
  125.  
  126.         ["Close information pane"] = "정보창 닫기",
  127.         ["Close this side informational pane"] = "이 정보창을 종료합니다.",
  128.  
  129.         ["Zones"] = "지역",
  130.         ["Cities"] = "도시",
  131.  
  132.         ["%.0f yd"] = "%.0f yd",
  133.         ["%.0f m"] = "%.0f 미터",
  134.         ["Cartographer"] = "Cartographer",
  135.         ["Open alternate map"] = "교체된 지도 열기",
  136.  
  137.         ["Addon to manipulate the map."] = "월드맵 확장 애드온",
  138. } end)
  139.  
  140. --Ananhaid checkpoint.($Date: 2009-04-17 00:45:12 +0000 (Fri, 17 Apr 2009) $)
  141. L:AddTranslations("zhCN", function() return {
  142.         ["Active"] = "启用", -- remove in a while (2006-12-08)
  143.         ["Enabled"] = "启用",
  144.         ["Suspend/resume this module."] = "暂停/继续使用该模块。",
  145.  
  146.         ["Right-Click on map to zoom out"] = "右击:放大地图",
  147.         ["Left-Click on map to zoom in"] = "左击:缩小地图",
  148.  
  149.         ["Go to %s"] = "回到%s",
  150.  
  151.         ["Open Cartographer menu"] = "打开 Cartographer 菜单",
  152.         ["Open location menu"] = "打开位置菜单",
  153.  
  154.         ["Distance:"] = "距离:",
  155.  
  156.         ["Close information pane"] = "关闭信息面板",
  157.         ["Close this side informational pane"] = "关闭这个侧信息面板。",
  158.  
  159.         ["Zones"] = "区域",
  160.         ["Cities"] = "城市",
  161.  
  162.         ["%.0f yd"] = "%.0f 码",
  163.         ["%.0f m"] = "%.0f 米",
  164.         ["Cartographer"] = "Cartographer",
  165.         ["Open alternate map"] = "打开替代地图",
  166.  
  167.         ["Addon to manipulate the map."] = "增强地图处理功能。",
  168. } end)
  169.  
  170. L:AddTranslations("zhTW", function() return {
  171.         ["Active"] = "啟用", -- remove in a while (2006-12-08)
  172.         ["Enabled"] = "啟用",
  173.         ["Suspend/resume this module."] = "暫停或繼續使用本模組。",
  174.  
  175.         ["Right-Click on map to zoom out"] = "|cffeda55f右擊: |r放大地圖",
  176.         ["Left-Click on map to zoom in"] = "|cffeda55f左擊: |r縮小地圖",
  177.  
  178.         ["Go to %s"] = "回到%s",
  179.  
  180.         ["Open Cartographer menu"] = "開啟 Cartographer 選單",
  181.         ["Open location menu"] = "開啟位置選單",
  182.  
  183.         ["Distance:"] = "距離:",
  184.  
  185.         ["Close information pane"] = "關閉資訊面板",
  186.         ["Close this side informational pane"] = "關閉這個側邊資訊面板",
  187.  
  188.         ["Zones"] = "地區",
  189.         ["Cities"] = "城市",
  190.  
  191.         ["%.0f yd"] = "%.0f碼",
  192.         ["%.0f m"] = "%.0f米",
  193.         ["Cartographer"] = "Cartographer",
  194.         ["Open alternate map"] = "開啟替代地圖",
  195.  
  196.         ["Addon to manipulate the map."] = "增強地圖的處理功能。",
  197. } end)
  198.  
  199. L:AddTranslations("esES", function() return {
  200.         ["Active"] = "Activo", -- remove in a while (2006-12-08)
  201.         ["Enabled"] = "Activado",
  202.         ["Suspend/resume this module."] = "Parar/Continuar este módulo",
  203.  
  204.         ["Right-Click on map to zoom out"] = "Click-Derecho en el mapa para Alejarte",
  205.         ["Left-Click on map to zoom in"] = "Click-Izquierdo en el mapa para Acercarte",
  206.  
  207.         ["Go to %s"] = "Ir a %s",
  208.  
  209.         ["Open Cartographer menu"] = "Abrir el menú de Cartographer",
  210.         ["Open location menu"] = "Abrir el menú de lugares",
  211.  
  212.         ["Distance:"] = "Distancia:",
  213.  
  214.         ["Close information pane"] = "Cerrar panel de información",
  215.         ["Close this side informational pane"] = "Cierra el panel de información de este lado",
  216.  
  217.         ["Zones"] = "Zonas",
  218.         ["Cities"] = "Ciudades",
  219.  
  220.         ["Open alternate map"] = "Abrir mapa alternativo",
  221.  
  222.         ["Addon to manipulate the map."] = "Addon para manipular el mapa.",
  223. } end)
  224.  
  225. -- Russian Translation by StingerSoft (Eritnull aka Шептун)
  226. L:AddTranslations("ruRU", function() return {
  227.         ["Active"] = "Активен",
  228.         ["Enabled"] = "Включен",
  229.         ["Suspend/resume this module."] = "Отключить/Запустить данный модуль",
  230.  
  231.         ["Right-Click on map to zoom out"] = "ПКЛ по карте для уменьшения масштаба",
  232.         ["Left-Click on map to zoom in"] = "ЛКМ по карте для увеличения масштаба",
  233.  
  234.         ["Go to %s"] = "Перейти на %s",
  235.  
  236.         ["Open Cartographer menu"] = "Открыть меню Картографа",
  237.         ["Open location menu"] = "Открыть меню локации",
  238.  
  239.         ["Distance:"] = "Дистанция:",
  240.  
  241.         ["Close information pane"] = "Закрыть панель информации",
  242.         ["Close this side informational pane"] = "Закрыть боковую панель информации",
  243.  
  244.         ["Zones"] = "Зоны",
  245.         ["Cities"] = "Города",
  246.         ["%.0f yd"] = "%.0f м",
  247.         ["%.0f m"] = "%.0f м",
  248.         ["Cartographer"] = "Картограф",
  249.         ["Open alternate map"] = "Открыть альтернативную карту",
  250.  
  251.         ["Addon to manipulate the map."] = "Аддон для монипуляции картой.",
  252. } end)
  253.  
  254. BINDING_HEADER_CARTOGRAPHER = L["Cartographer"]
  255. BINDING_NAME_CARTOGRAPHER_OPENALTERNATEMAP = L["Open alternate map"]
  256.  
  257. local PLAYER = PLAYER or "PLAYER"
  258. local PARTY = PARTY or "PARTY"
  259. local RAID = RAID or "RAID"
  260. local RANK = RANK or "RANK"
  261. local GUILD = GUILD or "GUILD"
  262. local CLASS = CLASS or "CLASS"
  263. local RACE = RACE or "RACE"
  264. local LEVEL = LEVEL or "LEVEL"
  265. local NOTE_COLON = NOTE_COLON or "NOTE_COLON"
  266. local OFFICER_NOTE_COLON = OFFICER_NOTE_COLON or "OFFICER_NOTE_COLON"
  267. if not OFFICER_NOTE_COLON:find(':') then
  268.         OFFICER_NOTE_COLON = OFFICER_NOTE_COLON .. ':'
  269. end
  270.  
  271. local yardString = (GetLocale() == "enUS" or GetLocale() == "zhTW" or GetLocale() == "zhCN") and L["%.0f yd"] or L["%.0f m"]
  272.  
  273. function Cartographer:AcquireDBNamespace(...)
  274.         return self:GetDatabaseNamespace(...)
  275. end
  276. function Cartographer:RegisterDefaults(...)
  277.         return self:SetDatabaseNamespaceDefaults(...)
  278. end
  279.  
  280. Cartographer.options = {
  281.         type = 'group',
  282.         name = L["Cartographer"],
  283.         desc = L["Addon to manipulate the map."],
  284.         icon = [[Interface\WorldMap\UI-World-Icon]],
  285.         args = {
  286.         },
  287. }
  288.  
  289. --[[
  290. local function ConvertToRockConfig(opt)
  291.         if opt.type == "group" then
  292.                 for k, v in pairs(opt.args) do
  293.                         ConvertToRockConfig(v)
  294.                 end
  295.         elseif opt.type == "toggle" then
  296.                 opt.type = "boolean"
  297.         elseif opt.type == "range" then
  298.                 opt.type = "number"
  299.         elseif opt.type == "text" then
  300.                 if not opt.validate or type(opt.validate) == "function" or type(opt.validate) == "string" then
  301.                         opt.type = "string"
  302.                 else
  303.                         if opt.multiToggle then
  304.                                 opt.type = "multichoice"
  305.                                 opt.multiToggle = nil
  306.                         else
  307.                                 opt.type = "choice"
  308.                         end
  309.                         opt.choices, opt.validate = opt.validate, nil
  310.                         opt.choiceDescs, opt.validateDesc = opt.validateDesc, nil
  311.                 end
  312.         elseif opt.type == "execute" then
  313.                 if not opt.buttonText then
  314.                         opt.buttonText = _G.OKAY or "Okay"
  315.                 end
  316.         end
  317. end
  318. setmetatable(Cartographer.options.args, {__newindex=function(self, key, value)
  319.         if type(value) == "table" then
  320.                 ConvertToRockConfig(value)
  321.         end
  322.         rawset(self, key, value)
  323. end})
  324. ]]
  325. --Dewdrop:InjectAceOptionsTable(Cartographer, Cartographer.options)
  326. --Cartographer.options.args.standby = nil
  327.  
  328. function Cartographer:OnInitialize()
  329.         if not self.db.account.firstTimeWoW21 then
  330.                 self.db.account.firstTimeWoW21 = true
  331.                 SetCVar("scriptErrors", "1")
  332.         end
  333.  
  334.         self.gotoOptions = {
  335.                 type = 'group',
  336.                 args = {
  337.                         player = {
  338.                                 name = string.format(L["Go to %s"], GetRealZoneText()),
  339.                                 desc = string.format(L["Go to %s"], GetRealZoneText()),
  340.                                 type = 'execute',
  341.                                 func = function()
  342.                                         SetMapToCurrentZone()
  343.                                 end,
  344.                                 order = 1
  345.                         }
  346.                 },
  347.         }
  348.         local original_WorldMapButton_OnClick = WorldMapButton_OnClick
  349.         -- override of function found in FrameXML/WorldMapFrame.lua:550
  350.         function WorldMapButton_OnClick(button, mouseButton)
  351.                 if mouseButton == "LeftButton" or mouseButton == "RightButton" then
  352.                         return original_WorldMapButton_OnClick(button, mouseButton)
  353.                 end
  354.         end
  355.  
  356.         self.lodMenus = setmetatable({}, {__mode = 'k'})
  357.  
  358.         WorldMapFrameCloseButton:SetScript("OnClick", function()
  359.                 ToggleFrame(WorldMapFrame)
  360.         end)
  361.  
  362.         self:SetConfigTable(self.options)
  363.         self:SetConfigSlashCommand("/Cartographer", "/Cart")
  364.         self.options.extraArgs.active = nil
  365. end
  366.  
  367. local magnifyingGlassTexts = { L["Right-Click on map to zoom out"], L["Left-Click on map to zoom in"] }
  368. local currentLeftSide, currentRightSide
  369. local dummyFrame
  370. function Cartographer:OnEnable()
  371.         WorldMapContinentDropDown:Hide()
  372.         WorldMapZoneDropDown:Hide()
  373.  
  374.         local CartographerOptionsButton = CreateFrame("Button", "CartographerOptionsButton", WorldMapFrame, "UIPanelButtonTemplate")
  375.         CartographerOptionsButton:SetText(L["Cartographer"])
  376.         local width = CartographerOptionsButton:GetTextWidth() + 30
  377.         if width < 110 then
  378.                 width = 110
  379.         end
  380.         CartographerOptionsButton:SetWidth(width)
  381.         CartographerOptionsButton:SetHeight(22)
  382.         WorldMapZoomOutButton:Hide()
  383.         CartographerOptionsButton:SetScript("OnClick", function()
  384.                 self:OpenConfigMenu()
  385. --[[            Dewdrop:Register(this,
  386.                         'children', self.options,
  387.                         'dontHook', true,
  388.                         'point', "TOPRIGHT",
  389.                         'relativePoint', "BOTTOMRIGHT"
  390.                 )
  391.                 this:SetScript("OnClick", function()
  392.                         if Dewdrop:IsOpen(this) then
  393.                                 Dewdrop:Close()
  394.                         else
  395.                                 Dewdrop:Open(this)
  396.                         end
  397.                 end)
  398.                 this:GetScript("OnClick")()]]
  399.         end)
  400.         CartographerOptionsButton:SetScript("OnEnter", function(this)
  401.                 GameTooltip_SetDefaultAnchor(GameTooltip, this)
  402.                 GameTooltip:SetText(L["Open Cartographer menu"], HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
  403.                 GameTooltip:Show()
  404.         end)
  405.         CartographerOptionsButton:SetScript("OnLeave", function(this)
  406.                 GameTooltip:Hide()
  407.         end)
  408.         self:AddMapButton(CartographerOptionsButton, 1)
  409.  
  410.         local CartographerGoToButton = CreateFrame("Button", "CartographerGoToButton", WorldMapFrame, "UIPanelButtonTemplate")
  411.         CartographerGoToButton:SetText(UNKNOWN)
  412.         local width = CartographerGoToButton:GetTextWidth() + 30
  413.         if width < 220 then
  414.                 width = 220
  415.         end
  416.         CartographerGoToButton:SetWidth(width)
  417.         CartographerGoToButton:SetHeight(22)
  418.         CartographerGoToButton:SetScript("OnClick", function()
  419.                 Dewdrop:Register(this,
  420.                         'children', self.gotoOptions,
  421.                         'dontHook', true,
  422.                         'point', "TOPRIGHT",
  423.                         'relativePoint', "BOTTOMRIGHT"
  424.                 )
  425.                 this:SetScript("OnClick", function()
  426.                         if Dewdrop:IsOpen(this) then
  427.                                 Dewdrop:Close()
  428.                         else
  429.                                 Dewdrop:Open(this)
  430.                         end
  431.                 end)
  432.                 this:GetScript("OnClick")()
  433.         end)
  434.         CartographerGoToButton:SetScript("OnEnter", function(this)
  435.                 GameTooltip_SetDefaultAnchor(GameTooltip, this)
  436.                 GameTooltip:SetText(L["Open location menu"], HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
  437.                 GameTooltip:Show()
  438.         end)
  439.         CartographerGoToButton:SetScript("OnLeave", function(this)
  440.                 GameTooltip:Hide()
  441.         end)
  442.         self:AddMapButton(CartographerGoToButton, 0)
  443.  
  444.         self:AddSecureHook(WorldMapFrame, "Hide", "WorldMapFrame_Hide")
  445.         self:AddSecureHook(WorldMapFrame, "Show", "WorldMapFrame_Show")
  446.         self:AddEventListener("Cartographer", "MapOpened", "Cartographer_MapOpened")
  447.         self:AddEventListener("Cartographer", "MapClosed", "Cartographer_MapClosed")
  448.         self:AddEventListener("Cartographer", "ChangeZone", "Cartographer_ChangeZone")
  449.         self:AddEventListener("WORLD_MAP_UPDATE")
  450.         self:AddEventListener("ZONE_CHANGED_NEW_AREA")
  451.         self:AddEventListener("MINIMAP_ZONE_CHANGED")
  452.         self:AddEventListener("LibRock-1.0", "FullyInitialized")
  453.         AceEvent = Rock("AceEvent-2.0", true, true)
  454.         if not AceEvent then
  455.                 self:AddEventListener("LibRock-1.0", "LibraryLoad", function(major, library)
  456.                         if major == "AceEvent-2.0" then
  457.                                 AceEvent = library
  458.                                 self:RemoveEventListener("LibRock-1.0", "LibraryLoad")
  459.                         end
  460.                 end)
  461.         end
  462.  
  463.         self:Cartographer_ChangeZone("Cartographer", "ChangeZone", self:GetCurrentEnglishZoneName(), self:GetCurrentLocalizedZoneName())
  464.  
  465.         WorldMapMagnifyingGlassButton:SetText(table.concat(magnifyingGlassTexts, "\n"))
  466.  
  467.         if (not GetBindingAction("ALT-M") or GetBindingAction("ALT-M") == "") and not GetBindingKey("CARTOGRAPHER_OPENALTERNATEMAP") then
  468.                 SetBinding("ALT-M", "CARTOGRAPHER_OPENALTERNATEMAP")
  469.         end
  470.  
  471.         for i = 1, 2 do
  472.                 local side = i == 1 and "LEFT" or "RIGHT"
  473.                 local s = "Cartographer_" .. side .. "Side"
  474.                 Tablet:Register(s,
  475.                         'data', {},
  476.                         'children', side == "LEFT" and function()
  477.                                 if currentLeftSide then
  478.                                         currentLeftSide:OnCartographerLeftTabletRequest()
  479.                                 end
  480.                         end or function()
  481.                                 if currentRightSide then
  482.                                         currentRightSide:OnCartographerRightTabletRequest()
  483.                                 end
  484.                         end,
  485.                         'clickable', true,
  486.                         'dontHook', true,
  487.                         'cantAttach', true,
  488.                         'frameLevel', 11,
  489.                         'movable', false,
  490.                         'hideWhenEmpty', true,
  491.                         'parent', WorldMapFrame,
  492.                         'showTitleWhenDetached', true,
  493.                         'showHintWhenDetached', true,
  494.                         'positionFunc', side == "LEFT" and function(this)
  495.                                 this:SetPoint("TOPLEFT", WorldMapDetailFrame, "TOPLEFT")
  496.                                 this:SetPoint("BOTTOMLEFT", WorldMapDetailFrame, "BOTTOMLEFT")
  497.                         end or function(this)
  498.                                 this:SetPoint("TOPRIGHT", WorldMapDetailFrame, "TOPRIGHT")
  499.                                 this:SetPoint("BOTTOMRIGHT", WorldMapDetailFrame, "BOTTOMRIGHT")
  500.                         end,
  501.                         'menu', function()
  502.                                 Dewdrop:AddLine(
  503.                                         'text', L["Close information pane"],
  504.                                         'tooltipTitle', L["Close information pane"],
  505.                                         'tooltipText', L["Close this side informational pane"],
  506.                                         'arg1', self,
  507.                                         'func', "ReleaseSideTablet",
  508.                                         'arg2', side,
  509.                                         'closeWhenClicked', true
  510.                                 )
  511.                         end
  512.                 )
  513.                 if WorldMapFrame:IsShown() then
  514.                         Tablet:Open(s)
  515.                 end
  516.         end
  517.  
  518.         self:ConfigureUnitPOIs()
  519.  
  520.         self:configureYards()
  521.  
  522.         self:LoadLoadOnDemandModules()
  523.  
  524.         self:AddEventListener("PLAYER_LEVEL_UP")
  525.         self:AddEventListener("LibRockEvent-1.0", "FullyInitialized")
  526.         self:PLAYER_LEVEL_UP()
  527. end
  528.  
  529. function Cartographer:PLAYER_LEVEL_UP()
  530.         self.gotoOptions.args.Cities = {
  531.                 name = L["Cities"],
  532.                 desc = L["Cities"],
  533.                 type = 'group',
  534.                 args = {}
  535.         }
  536.         self.gotoOptions.args.Zones = {
  537.                 name = L["Zones"],
  538.                 desc = L["Zones"],
  539.                 type = 'group',
  540.                 args = {}
  541.         }
  542.         for i,continent in ipairs { GetMapContinents() } do
  543.                 local i = i
  544.                 local validate = { GetMapZones(i) }
  545.                 local zones = {}
  546.                 local cities = {}
  547.                 for i, v in ipairs(validate) do
  548.                         local text = v
  549.                         local low, high = Tourist:GetLevel(v)
  550.                         local r, g, b = Tourist:GetLevelColor(v)
  551.                         local levelText
  552.                         if low == 0 then
  553.                                 levelText = ""
  554.                         elseif low == high then
  555.                                 levelText = (" |cff%02x%02x%02x[%d]|r"):format(r * 255, g * 255, b * 255, high)
  556.                         else
  557.                                 levelText = (" |cff%02x%02x%02x[%d-%d]|r"):format(r * 255, g * 255, b * 255, low, high)
  558.                         end
  559.                         local r, g, b = Tourist:GetFactionColor(v)
  560.                         text = ("|cff%02x%02x%02x%s|r%s"):format(r*255, g*255, b*255, text, levelText)
  561.                         if Tourist:IsCity(v) then
  562.                                 cities[v] = text
  563.                         else
  564.                                 zones[v] = text
  565.                         end
  566.                         validate[v] = i
  567.                 end
  568.                 self.gotoOptions.args.Zones.args[BZR[continent]] = {
  569.                         name = continent,
  570.                         desc = continent,
  571.                         type = 'text',
  572.                         validate = zones,
  573.                         get = function() return self:GetCurrentInstance() or GetCurrentMapContinent() == i and validate[GetCurrentMapZone()] end,
  574.                         set = function(text)
  575.                                 SetMapZoom(i, validate[text])
  576.                         end,
  577.                 }
  578.                 self.gotoOptions.args.Cities.args[BZR[continent]] = {
  579.                         name = continent,
  580.                         desc = continent,
  581.                         type = 'text',
  582.                         validate = cities,
  583.                         get = function() return self:GetCurrentInstance() or GetCurrentMapContinent() == i and validate[GetCurrentMapZone()] end,
  584.                         set = function(text)
  585.                                 SetMapZoom(i, validate[text])
  586.                         end,
  587.                 }
  588.         end
  589. end
  590.  
  591. function Cartographer:ConfigureUnitPOIs()
  592.         local old = WorldMapParty1:GetScript("OnLeave")
  593.         function WorldMapUnit_OnLeave()
  594.                 old(this)
  595.         end
  596.         local function func(this, ...)
  597.                 WorldMapUnit_OnLeave()
  598.         end
  599.         WorldMapPlayer:SetScript("OnLeave", func)
  600.         local myServer = GetRealmName():trim()
  601.         function WorldMapPlayer:OnTabletRequest()
  602.                 local kind = ""
  603.                 if self.unit == "player" then
  604.                         kind = PLAYER .. ": "
  605.                 elseif self.unit:find("^party") then
  606.                         kind = PARTY .. ": "
  607.                 elseif self.unit:find("^raid") then
  608.                         kind = RAID .. ": "
  609.                 end
  610.                 local name, server = self.name
  611.                 if not name then
  612.                         name, server = UnitName(self.unit)
  613.                 end
  614.                 if server and server ~= myServer and server ~= "" then
  615.                         name = name .. '-' .. server
  616.                 end
  617.                 Tablet:SetTitle(kind .. name)
  618.                 if self.unit then
  619.                         local cat = Tablet:AddCategory('columns', 2)
  620.                         local class, filename = UnitClass(self.unit)
  621.                         local color = RAID_CLASS_COLORS[filename]
  622.                         cat:AddLine(
  623.                                 'text', CLASS .. ":",
  624.                                 'text2', class,
  625.                                 'text2R', color.r,
  626.                                 'text2G', color.g,
  627.                                 'text2B', color.b
  628.                         )
  629.                         local level = UnitLevel(self.unit)
  630.                         local playerlevel = UnitLevel('player')
  631.                         local r, g, b = Crayon:GetThresholdColorTrivial(level, playerlevel + 6, playerlevel - 6)
  632.                         cat:AddLine(
  633.                                 'text', LEVEL .. ":",
  634.                                 'text2', level,
  635.                                 'text2R', r,
  636.                                 'text2G', g,
  637.                                 'text2B', b
  638.                         )
  639.                         cat:AddLine(
  640.                                 'text', RACE .. ":",
  641.                                 'text2', (UnitRace(self.unit)),
  642.                                 'text2R', UnitRace(self.unit) == UnitRace('player') and 0 or 1,
  643.                                 'text2G', 1,
  644.                                 'text2B', 0
  645.                         )
  646.                         local gname, grank, granknum = GetGuildInfo(self.unit)
  647.                         if not gname then
  648.                                 if LibGuild:HasMember(name) then
  649.                                         gname = LibGuild:GetGuildName()
  650.                                         grank = LibGuild:GetRank(name)
  651.                                         granknum = LibGuild:GetRankIndex(name)
  652.                                 end
  653.                         end
  654.                         if gname then
  655.                                 local mygname, mygrank, mygranknum = GetGuildInfo('player')
  656.                                 local r, g, b = 1, 1, 0
  657.                                 if mygname == gname then
  658.                                         r, g, b = 0, 1, 0
  659.                                 end
  660.                                 cat:AddLine(
  661.                                         'text', GUILD .. ":",
  662.                                         'text2', "<" .. gname .. ">",
  663.                                         'text2R', r,
  664.                                         'text2G', g,
  665.                                         'text2B', b
  666.                                 )
  667.                                 if mygname == gname then
  668.                                         local grankdiff = granknum - mygranknum
  669.                                         if grankdiff >= 2 then
  670.                                                 r, g, b = 0, 1, 0
  671.                                         elseif grankdiff == 1 then
  672.                                                 r, g, b = 0.5, 1, 0
  673.                                         elseif grankdiff == 0 then
  674.                                                 r, g, b = 1, 1, 0
  675.                                         elseif grankdiff == -1 then
  676.                                                 r, g, b = 1, 0.5, 0
  677.                                         else
  678.                                                 r, g, b = 1, 0, 0
  679.                                         end
  680.                                 end
  681.                                 cat:AddLine(
  682.                                         'text', RANK .. ":",
  683.                                         'text2', grank,
  684.                                         'text2R', r,
  685.                                         'text2G', g,
  686.                                         'text2B', b
  687.                                 )
  688.                                 if mygname == gname then
  689.                                         local note, onote = LibGuild:GetNote(name), LibGuild:GetOfficerNote(name)
  690.  
  691.                                         if note then
  692.                                                 cat:AddLine(
  693.                                                         'text', NOTE_COLON,
  694.                                                         'text2', note,
  695.                                                         'text2R', 1,
  696.                                                         'text2G', 1,
  697.                                                         'text2B', 0
  698.                                                 )
  699.                                         end
  700.  
  701.                                         if onote then
  702.                                                 cat:AddLine(
  703.                                                         'text', OFFICER_NOTE_COLON,
  704.                                                         'text2', onote,
  705.                                                         'text2R', 1,
  706.                                                         'text2G', 1,
  707.                                                         'text2B', 0
  708.                                                 )
  709.                                         end
  710.                                 end
  711.                         end
  712.                         local x, y = GetPlayerMapPosition(self.unit)
  713.                         local dist = Cartographer:GetDistanceToPoint(x, y, Cartographer:GetCurrentLocalizedZoneName())
  714.  
  715.                         if dist and dist >= 1 then
  716.                                 cat:AddLine(
  717.                                         'text', L["Distance:"],
  718.                                         'text2', yardString:format(dist)
  719.                                 )
  720.                         end
  721.                 end
  722.         end
  723.         WorldMapParty1.OnTabletRequest = WorldMapPlayer.OnTabletRequest
  724.         WorldMapRaid1.OnTabletRequest = WorldMapPlayer.OnTabletRequest
  725.         local tmp = {}
  726.         function WorldMapPlayer:OnLineRequest(cat)
  727.                 if self.unit == "player" then
  728.                         tmp[#tmp+1] = PLAYER .. ": "
  729.                 elseif self.unit:find("^party") then
  730.                         tmp[#tmp+1] = PARTY .. ": "
  731.                 elseif self.unit:find("^raid") then
  732.                         tmp[#tmp+1] = RAID .. ": "
  733.                 end
  734.                 if self.name then
  735.                         tmp[#tmp+1] = self.name
  736.                 else
  737.                         local name, server = UnitName(self.unit)
  738.                         tmp[#tmp+1] = name
  739.                         if server and server ~= myServer and server ~= "" then
  740.                                 tmp[#tmp+1] = "-"
  741.                                 tmp[#tmp+1] = server
  742.                         end
  743.                         tmp[#tmp+1] = " - |cff"
  744.                         local level = UnitLevel(self.unit)
  745.                         local playerlevel = UnitLevel('player')
  746.                         tmp[#tmp+1] = Crayon:GetThresholdHexColorTrivial(level, playerlevel + 6, playerlevel - 6)
  747.                         tmp[#tmp+1] = tostring(level)
  748.                         tmp[#tmp+1] = "|r |cff"
  749.                         local class, filename = UnitClass(self.unit)
  750.                         local color = RAID_CLASS_COLORS[filename]
  751.                         tmp[#tmp+1] = ("%02x%02x%02x"):format(color.r*255, color.g*255, color.b*255)
  752.                         tmp[#tmp+1] = class
  753.                         tmp[#tmp+1] = "|r"
  754.                         local gname = GetGuildInfo(self.unit)
  755.                         if not gname then
  756.                                 if LibGuild:HasMember(name) then
  757.                                         gname = LibGuild:GetGuildName()
  758.                                 end
  759.                         end
  760.                         if gname then
  761.                                 local mygname = LibGuild:GetGuildName()
  762.                                 tmp[#tmp+1] = " - |cff"
  763.                                 if gname == mygname then
  764.                                         tmp[#tmp+1] = "00ff00"
  765.                                 else
  766.                                         tmp[#tmp+1] = "ffff00"
  767.                                 end
  768.                                 tmp[#tmp+1] = "<"
  769.                                 tmp[#tmp+1] = gname
  770.                                 tmp[#tmp+1] = ">|r"
  771.                         end
  772.                 end
  773.                 local text = table.concat(tmp, "")
  774.                 for i = 1, #tmp do
  775.                         tmp[i] = nil
  776.                 end
  777.                 if self.unit == "player" then
  778.                         return 'text', text,
  779.                                 'hasCheck', true,
  780.                                 'checked', false
  781.                 else
  782.                         local tex = _G[self:GetName() .. "Icon"]
  783.                         local left, top, _, _, _, _, right, bottom = tex:GetTexCoord()
  784.                         local r, g, b = tex:GetVertexColor()
  785.                         return 'text', text,
  786.                                 'hasCheck', true,
  787.                                 'checked', true,
  788.                                 'checkIcon', tex:GetTexture(),
  789.                                 'checkCoordLeft', left,
  790.                                 'checkCoordRight', right,
  791.                                 'checkCoordTop', top,
  792.                                 'checkCoordBottom', bottom,
  793.                                 'checkColorR', r,
  794.                                 'checkColorG', g,
  795.                                 'checkColorB', b
  796.                 end
  797.         end
  798.         WorldMapPlayer:SetFrameLevel(WorldMapPlayer:GetFrameLevel()+5)
  799.         PlayerArrowFrame:SetFrameLevel(PlayerArrowFrame:GetFrameLevel()+5)
  800.         PlayerArrowEffectFrame:SetFrameLevel(PlayerArrowEffectFrame:GetFrameLevel()+5)
  801.         WorldMapParty1.OnLineRequest = WorldMapPlayer.OnLineRequest
  802.         WorldMapRaid1.OnLineRequest = WorldMapPlayer.OnLineRequest
  803.         for i = 1, 4 do
  804.                 local poi = _G["WorldMapParty" .. i]
  805.                 poi:SetScript("OnLeave", func)
  806.                 poi.OnTabletRequest = WorldMapParty1.OnTabletRequest
  807.                 poi.OnLineRequest = WorldMapParty1.OnLineRequest
  808.                 poi:SetFrameLevel(poi:GetFrameLevel()+3)
  809.         end
  810.         for i = 1, 40 do
  811.                 local poi = _G["WorldMapRaid" .. i]
  812.                 poi:SetScript("OnLeave", func)
  813.                 poi.OnTabletRequest = WorldMapRaid1.OnTabletRequest
  814.                 poi.OnLineRequest = WorldMapRaid1.OnLineRequest
  815.                 poi:SetFrameLevel(poi:GetFrameLevel()+3)
  816.         end
  817.  
  818.         dummyFrame = CreateFrame("Frame")
  819.         if not self.pois then
  820.                 self.pois = {}
  821.         end
  822.         local tmp = {}
  823.         self.tooltipData = {}
  824.         Tablet:Register(dummyFrame,
  825.                 'children', function()
  826.                         -- Check player
  827.                         if MouseIsOver(WorldMapPlayer) then
  828.                                 tmp[#tmp+1] = WorldMapPlayer
  829.                         end
  830.  
  831.                         -- Check party
  832.                         for i=1, MAX_PARTY_MEMBERS do
  833.                                 local unitButton = _G["WorldMapParty"..i]
  834.                                 if unitButton:IsVisible() and MouseIsOver(unitButton) then
  835.                                         tmp[#tmp+1] = unitButton
  836.                                 end
  837.                         end
  838.  
  839.                         --Check Raid
  840.                         for i=1, MAX_RAID_MEMBERS do
  841.                                 local unitButton = _G["WorldMapRaid"..i]
  842.                                 if unitButton:IsVisible() and MouseIsOver(unitButton) then
  843.                                         tmp[#tmp+1] = unitButton
  844.                                 end
  845.                         end
  846.  
  847.                         for frame in pairs(self.pois) do
  848.                                 if frame:IsVisible() and MouseIsOver(frame) then
  849.                                         tmp[#tmp+1] = frame
  850.                                 end
  851.                         end
  852.  
  853.                         if #tmp == 1 then
  854.                                 tmp[1]:OnTabletRequest()
  855.                                 tmp[1] = nil
  856.                         elseif #tmp > 1 then
  857.                                 local cat = Tablet:AddCategory()
  858.                                 for i = 1, #tmp do
  859.                                         cat:AddLine(tmp[i]:OnLineRequest())
  860.                                         tmp[i] = nil
  861.                                 end
  862.                         end
  863.                 end,
  864.                 'point', function(parent)
  865.                         local x, y = GetCursorPosition()
  866.                         local cx, cy = GetScreenWidth()/2, GetScreenHeight()/2
  867.                         if x > cx then
  868.                                 if y < cy then
  869.                                         return "BOTTOMRIGHT"
  870.                                 else
  871.                                         return "TOPRIGHT"
  872.                                 end
  873.                         else
  874.                                 if y < cy then
  875.                                         return "BOTTOMLEFT"
  876.                                 else
  877.                                         return "TOPLEFT"
  878.                                 end
  879.                         end
  880.                 end,
  881.                 'relativePoint', function(parent)
  882.                         local x, y = GetCursorPosition()
  883.                         local cx, cy = GetScreenWidth()/2, GetScreenHeight()/2
  884.                         if x > cx then
  885.                                 if y < cy then
  886.                                         return "TOPLEFT"
  887.                                 else
  888.                                         return "BOTTOMLEFT"
  889.                                 end
  890.                         else
  891.                                 if y < cy then
  892.                                         return "TOPRIGHT"
  893.                                 else
  894.                                         return "BOTTOMRIGHT"
  895.                                 end
  896.                         end
  897.                 end,
  898.                 'dontHook', true,
  899.                 'data', self.tooltipData
  900.         )
  901.         self:AddHook("WorldMapUnit_OnEnter")
  902.         self:AddHook("WorldMapUnit_OnLeave")
  903.         self:AddRepeatingTimer(1, "UpdateTooltip")
  904. end
  905.  
  906. do
  907.         local t = {}
  908.         local function tmp(...)
  909.                 for i = 1, #t do
  910.                         t[i] = nil
  911.                 end
  912.                 for i = 1, select('#', ...) do
  913.                         t[i] = select(i, ...)
  914.                 end
  915.                 return t
  916.         end
  917.         function Cartographer:LoadLoadOnDemandModules()
  918.                 for i = 1, GetNumAddOns() do
  919.                         local name, _, notes, enabled, loadable = GetAddOnInfo(i)
  920.                         if IsAddOnLoadOnDemand(i) and enabled and loadable and not IsAddOnLoaded(i) then
  921.                                 local shownName = GetAddOnMetadata(name, "X-Name")
  922.                                 local moduleName = GetAddOnMetadata(name, "X-ModuleName")
  923.                                 if shownName and moduleName then
  924.                                         Cartographer.options.args[moduleName] = nil
  925.                                         for _,dep in ipairs(tmp(GetAddOnDependencies(name))) do
  926.                                                 if dep == "Cartographer" then
  927.                                                         if self:IsModuleActive(moduleName, true) then
  928.                                                                 local success, ret = pcall(LoadAddOn, name)
  929.                                                                 if not success then
  930.                                                                         geterrorhandler()(ret)
  931.                                                                 end
  932.                                                         else
  933.                                                                 Cartographer.options.args[moduleName] = {
  934.                                                                         type = 'group',
  935.                                                                         name = shownName,
  936.                                                                         desc = notes,
  937.                                                                         args = {
  938.                                                                                 toggle = {
  939.                                                                                         name = L["Enabled"],
  940.                                                                                         desc = L["Suspend/resume this module."],
  941.                                                                                         type = "toggle",
  942.                                                                                         order = -1,
  943.                                                                                         get = function() return false end,
  944.                                                                                         set = function()
  945.                                                                                                 Cartographer.options.args[moduleName] = nil
  946.                                                                                                 local success, ret = pcall(LoadAddOn, name)
  947.                                                                                                 if not success then
  948.                                                                                                         geterrorhandler()(ret)
  949.                                                                                                 else
  950.                                                                                                         Cartographer:ToggleModuleActive(moduleName)
  951.                                                                                                 end
  952.                                                                                         end
  953.                                                                                 },
  954.                                                                         }
  955.                                                                 }
  956.                                                                 self.lodMenus[Cartographer.options.args[moduleName]] = true
  957.                                                         end
  958.                                                         break
  959.                                                 end
  960.                                         end
  961.                                 end
  962.                         end
  963.                 end
  964.                 if type(self.lodMenus) == 'table' and next(self.lodMenus) then
  965.                         self:AddEventListener("ADDON_LOADED")
  966.                 end
  967.         end
  968. end
  969.  
  970. function Cartographer:ADDON_LOADED(ns, event, addon)
  971.         local moduleName = GetAddOnMetadata(addon, "X-ModuleName")
  972.         if moduleName then
  973.                 if self.lodMenus[Cartographer.options.args[moduleName]] then
  974.                         Cartographer.options.args[moduleName] = nil
  975.                 end
  976.         end
  977. end
  978.  
  979. local isOpen = false
  980. function Cartographer:WorldMapUnit_OnEnter()
  981.         if not Dewdrop:IsOpen(this) then
  982.                 isOpen = true
  983.                 Tablet:Open(this, dummyFrame)
  984.         end
  985. end
  986.  
  987. function Cartographer:WorldMapUnit_OnLeave()
  988.         isOpen = false
  989.         Tablet:Close()
  990. end
  991.  
  992. function Cartographer:UpdateTooltip()
  993.         self:GetCurrentPlayerPosition()
  994.         if isOpen then
  995.                 Tablet:Refresh(dummyFrame)
  996.         end
  997. end
  998.  
  999. function Cartographer:AddPOI(frame)
  1000.         if not self.pois then
  1001.                 self.pois = {}
  1002.         end
  1003.         self.pois[frame] = true
  1004. end
  1005.  
  1006. local previouslyShown = false
  1007. function Cartographer:WorldMapFrame_Hide(this)
  1008.         if previouslyShown then
  1009.                 previouslyShown = false
  1010.                 self:DispatchEvent("MapClosed")
  1011.                 if AceEvent then
  1012.                         AceEvent:TriggerEvent("Cartographer_MapClosed")
  1013.                 end
  1014.         end
  1015.         if BattlefieldMinimap then
  1016.                 BattlefieldMinimap:SetScript("OnUpdate", BattlefieldMinimap_OnUpdate)
  1017.         end
  1018. end
  1019.  
  1020. function Cartographer:WorldMapFrame_Show(this)
  1021.         if not previouslyShown then
  1022.                 previouslyShown = true
  1023.                 self:DispatchEvent("MapOpened")
  1024.                 if AceEvent then
  1025.                         AceEvent:TriggerEvent("Cartographer_MapOpened")
  1026.                 end
  1027.         end
  1028.         if BattlefieldMinimap then
  1029.                 BattlefieldMinimap:SetScript("OnUpdate", nil)
  1030.         end
  1031. end
  1032.  
  1033. function Cartographer:WORLD_MAP_UPDATE()
  1034.         self:GetCurrentPlayerPosition()
  1035.         self:DispatchEvent("ChangeZone", self:GetCurrentEnglishZoneName(), self:GetCurrentLocalizedZoneName())
  1036.         if AceEvent then
  1037.                 AceEvent:TriggerEvent("Cartographer_ChangeZone", self:GetCurrentEnglishZoneName(), self:GetCurrentLocalizedZoneName())
  1038.         end
  1039. end
  1040.  
  1041. local function func(self)
  1042.         if currentLeftSide then
  1043.                 Tablet:Open("Cartographer_LEFTSide")
  1044. --              Tablet:Refresh("Cartographer_LEFTSide")
  1045.         end
  1046.         if currentRightSide then
  1047.                 Tablet:Open("Cartographer_RIGHTSide")
  1048.         end
  1049. end
  1050.  
  1051. function Cartographer:Cartographer_MapOpened()
  1052.         self:AddTimer(0, func, self)
  1053.         Tablet:Refresh("Cartographer_LEFTSide")
  1054.         Tablet:Refresh("Cartographer_RIGHTSide")
  1055. end
  1056.  
  1057. function Cartographer:Cartographer_MapClosed()
  1058.         if Dewdrop:IsOpen(CartographerGoToButton) or Dewdrop:IsOpen(CartographerOptionsButton) then
  1059.                 Dewdrop:Close()
  1060.         end
  1061.         SetMapToCurrentZone()
  1062. end
  1063.  
  1064. local continents = { GetMapContinents() }
  1065. continents[0] = BZL["Azeroth"]
  1066. continents[-1] = BZL["Cosmic map"]
  1067.  
  1068. function Cartographer:Cartographer_ChangeZone(ns, event, zone, localZone)
  1069.         if localZone then
  1070.                 CartographerGoToButton:SetText(localZone)
  1071.                 Cartographer.gotoOptions.args.player.name = string.format(L["Go to %s"], GetRealZoneText())
  1072.                 Cartographer.gotoOptions.args.player.desc = Cartographer.gotoOptions.args.player.name
  1073.         else
  1074.                 CartographerGoToButton:SetText(continents[GetCurrentMapContinent()] or UNKNOWN)
  1075.         end
  1076. end
  1077.  
  1078. function Cartographer:OnProfileEnable(alpha, bravo)
  1079.         self:LoadLoadOnDemandModules()
  1080.         for _,module in self:IterateModules() do
  1081.                 if self:IsModuleActive(module) and type(module.OnProfileEnable) == "function" then
  1082.                         module:OnProfileEnable(alpha, bravo)
  1083.                 end
  1084.         end
  1085. end
  1086.  
  1087. function Cartographer:AddToMagnifyingGlass(text)
  1088.         for _,v in ipairs(magnifyingGlassTexts) do
  1089.                 if v == text then
  1090.                         error(string.format("Cannot add %q to magnifying glass, it already exists", text), 2)
  1091.                 end
  1092.         end
  1093.         table.insert(magnifyingGlassTexts, text)
  1094.         WorldMapMagnifyingGlassButton:SetText(table.concat(magnifyingGlassTexts, "\n"))
  1095. end
  1096.  
  1097. function Cartographer:RemoveFromMagnifyingGlass(text)
  1098.         local id
  1099.         for i,v in ipairs(magnifyingGlassTexts) do
  1100.                 if v == text then
  1101.                         id = i
  1102.                         break
  1103.                 end
  1104.         end
  1105.         if not id then
  1106.                 error(string.format("Cannot remove %q from magnifying glass, it does not exist", text), 2)
  1107.         end
  1108.         table.remove(magnifyingGlassTexts, id)
  1109.  
  1110.         WorldMapMagnifyingGlassButton:SetText(table.concat(magnifyingGlassTexts, "\n"))
  1111. end
  1112.  
  1113. local mapButtons = {}
  1114.  
  1115. local function my_sort(alpha, bravo)
  1116.         if not alpha or not bravo then
  1117.                 return false
  1118.         end
  1119.         return mapButtons[alpha] < mapButtons[bravo]
  1120. end
  1121.  
  1122. local tmp = {}
  1123. local function refreshMapButtons()
  1124.         for k in pairs(mapButtons) do
  1125.                 table.insert(tmp, k)
  1126.         end
  1127.  
  1128.         table.sort(tmp, my_sort)
  1129.  
  1130.         local width = -10
  1131.         for _,frame in ipairs(tmp) do
  1132.                 width = width + frame:GetWidth() + 10
  1133.         end
  1134.  
  1135.         local last = tmp[1]
  1136.         last:SetPoint("BOTTOM", WorldMapZoomOutButton, "BOTTOM", 0, 0)
  1137.         last:SetPoint("LEFT", WorldMapDetailFrame, "CENTER", -width/2, 0)
  1138.         for i = 2, #tmp do
  1139.                 local this = tmp[i]
  1140.                 this:SetPoint("LEFT", last, "RIGHT", 10, 0)
  1141.                 last = this
  1142.         end
  1143.  
  1144.         for k in pairs(tmp) do
  1145.                 tmp[k] = nil
  1146.         end
  1147. end
  1148.  
  1149. function Cartographer:AddMapButton(frame, order)
  1150.         if mapButtons[frame] then
  1151.                 error(string.format("Cannot add %q to map buttons, it already exists", frame:GetName() or "anonymous frame"), 2)
  1152.         end
  1153.         mapButtons[frame] = order
  1154.  
  1155.         refreshMapButtons()
  1156. end
  1157.  
  1158. function Cartographer:RemoveMapButton(frame)
  1159.         if not mapButtons[frame] then
  1160.                 error(string.format("Cannot remove %q from map buttons, it does not exist", frame:GetName() or "anonymous frame"), 2)
  1161.         end
  1162.         mapButtons[frame] = nil
  1163.  
  1164.         refreshMapButtons()
  1165. end
  1166.  
  1167. local currentInstance
  1168. function Cartographer:SetCurrentInstance(zone)
  1169.         if currentInstance ~= zone then
  1170.                 currentInstance = zone
  1171.                 self:DispatchEvent("SetCurrentInstance", zone)
  1172.                 if AceEvent then
  1173.                         AceEvent:TriggerEvent("Cartographer_SetCurrentInstance", zone)
  1174.                 end
  1175.                 self:DispatchEvent("ChangeZone", self:GetCurrentEnglishZoneName(), self:GetCurrentLocalizedZoneName())
  1176.                 if AceEvent then
  1177.                         AceEvent:TriggerEvent("Cartographer_ChangeZone", self:GetCurrentEnglishZoneName(), self:GetCurrentLocalizedZoneName())
  1178.                 end
  1179.                 WorldMapLevelDropDown_Update()
  1180.         end
  1181. end
  1182.  
  1183. function Cartographer:GetCurrentInstance()
  1184.         return currentInstance
  1185. end
  1186.  
  1187. local instanceWorldMapButton
  1188. function Cartographer:RegisterInstanceWorldMapButton(frame)
  1189.         instanceWorldMapButton = frame
  1190.         self:DispatchEvent("RegisterInstanceWorldMapButton", frame)
  1191.         if AceEvent then
  1192.                 AceEvent:TriggerEvent("Cartographer_RegisterInstanceWorldMapButton", frame)
  1193.         end
  1194. end
  1195.  
  1196. function Cartographer:GetInstanceWorldMapButton()
  1197.         return instanceWorldMapButton
  1198. end
  1199.  
  1200. local mapZones = setmetatable({}, {__index = function(self, key)
  1201.         self[key] = { GetMapZones(key) }
  1202.         return self[key]
  1203. end })
  1204.  
  1205. function Cartographer:GetCurrentLocalizedZoneName()
  1206.         if currentInstance then
  1207.                 return BZL[currentInstance]
  1208.         end
  1209.         local map = GetMapInfo()
  1210.         if not map then
  1211.                 if GetCurrentMapZone() == 0 then
  1212.                         if GetCurrentMapContinent() == 0 then
  1213.                                 return BZL["Azeroth"]
  1214.                         elseif GetCurrentMapContinent() == -1 then
  1215.                                 return BZL["Cosmic map"]
  1216.                         end
  1217.                 end
  1218.         end
  1219.         return Tourist:GetZoneFromTexture(map)
  1220. end
  1221.  
  1222. function Cartographer:GetCurrentEnglishZoneName()
  1223.         if currentInstance then
  1224.                 return currentInstance
  1225.         end
  1226.         local map = GetMapInfo()
  1227.         if not map then
  1228.                 if GetCurrentMapZone() == 0 then
  1229.                         if GetCurrentMapContinent() == 0 then
  1230.                                 return "Azeroth"
  1231.                         elseif GetCurrentMapContinent() == -1 then
  1232.                                 return "Cosmic map"
  1233.                         end
  1234.                 end
  1235.         end
  1236.         return Tourist:GetEnglishZoneFromTexture(map)
  1237. end
  1238.  
  1239. function Cartographer:OpenAlternateMap()
  1240.         if self:GetProfile() == "Default" or self:GetProfile() == "Alternate" then
  1241.                 self:SetProfile(self:GetProfile() == "Default" and "Alternate" or "Default")
  1242.         end
  1243.  
  1244.         if not WorldMapFrame:IsShown() then
  1245.                 ToggleFrame(WorldMapFrame)
  1246.         end
  1247. end
  1248.  
  1249. function Cartographer:AcquireSideTablet(side, id)
  1250.         if side == "LEFT" then
  1251.                 currentLeftSide = id
  1252.         else -- RIGHT
  1253.                 currentRightSide = id
  1254.         end
  1255.         local s = "Cartographer_" .. side .. "Side"
  1256.         if WorldMapFrame:IsShown() then
  1257.                 Tablet:Refresh(s)
  1258.         end
  1259. end
  1260. precondition(Cartographer, "AcquireSideTablet", function(self, side, id)
  1261.         argCheck(side, 2, "string")
  1262.         if side ~= "LEFT" and side ~= "RIGHT" then
  1263.                 error('Argument #2 to `AcquireSideTablet\' must either be "LEFT" or "RIGHT".', 3)
  1264.         end
  1265.         argCheck(id, 3, "table")
  1266.         if side == "LEFT" then
  1267.                 if type(id.OnCartographerLeftTabletRequest) ~= "function" then
  1268.                         error("Argument #3 must include the method `OnCartographerLeftTabletRequest'.", 3)
  1269.                 end
  1270.         else -- RIGHT
  1271.                 if type(id.OnCartographerRightTabletRequest) ~= "function" then
  1272.                         error("Argument #3 must include the method `OnCartographerRightTabletRequest'.", 3)
  1273.                 end
  1274.         end
  1275. end)
  1276.  
  1277. function Cartographer:ReleaseSideTablet(side, id)
  1278.         if side == "LEFT" then
  1279.                 if not id or id == currentLeftSide then
  1280.                         currentLeftSide = nil
  1281.                 else
  1282.                         return
  1283.                 end
  1284.         else -- RIGHT
  1285.                 if not id or id == currentRightSide then
  1286.                         currentRightSide = nil
  1287.                 else
  1288.                         return
  1289.                 end
  1290.         end
  1291.         Tablet:Refresh("Cartographer_" .. side .. "Side")
  1292. end
  1293. precondition(Cartographer, "ReleaseSideTablet", function(self, side, id)
  1294.         argCheck(side, 2, "string")
  1295.         if side ~= "LEFT" and side ~= "RIGHT" then
  1296.                 error('Argument #2 to `ReleaseSideTablet\' must either be "LEFT" or "RIGHT".', 3)
  1297.         end
  1298.         argCheck(id, 3, "table", "nil")
  1299. end)
  1300.  
  1301. function Cartographer:GetCurrentSideTabletHandler(side)
  1302.         if side == "LEFT" then
  1303.                 return currentLeftSide
  1304.         else -- RIGHT
  1305.                 return currentRightSide
  1306.         end
  1307. end
  1308. precondition(Cartographer, "GetCurrentSideTabletHandler", function(self, side)
  1309.         argCheck(side, 2, "string")
  1310.         if side ~= "LEFT" and side ~= "RIGHT" then
  1311.                 error('Argument #2 to `ReleaseSideTablet\' must either be "LEFT" or "RIGHT".', 3)
  1312.         end
  1313. end)
  1314.  
  1315. function Cartographer:RefreshSideTablet(side, id)
  1316.         if not side then
  1317.                 self:RefreshSideTablet("LEFT", id)
  1318.                 self:RefreshSideTablet("RIGHT", id)
  1319.                 return
  1320.         end
  1321.         local s = "Cartographer_" .. side .. "Side"
  1322.         --if not Tablet:IsRegistered(s) then
  1323.         --      return
  1324.         --end
  1325.         if side == "LEFT" then
  1326.                 if id and id ~= currentLeftSide then
  1327.                         return
  1328.                 end
  1329.         else -- RIGHT
  1330.                 if id and id ~= currentRightSide then
  1331.                         return
  1332.                 end
  1333.         end
  1334.         Tablet:Open(s)
  1335. end
  1336. precondition(Cartographer, 'RefreshSideTablet', function(self, side, id)
  1337.         argCheck(side, 2, "string", "nil")
  1338.         if not side then
  1339.                 return
  1340.         end
  1341.         if side ~= "LEFT" and side ~= "RIGHT" then
  1342.                 error('Argument #2 to `AcquireSideTablet\' must either be "LEFT" or "RIGHT".', 3)
  1343.         end
  1344.         argCheck(id, 3, "table", "nil")
  1345. end)
  1346.  
  1347. local currentYardWidth, currentYardHeight = 1000, 1000 * 2/3
  1348.  
  1349. do
  1350.         local last_px, last_py
  1351.  
  1352.         local x, y, zone
  1353.         function Cartographer:GetCurrentPlayerPosition()
  1354.                 local px, py = GetPlayerMapPosition("player")
  1355.                 if px == last_px and py == last_py and x~=nil then      -- Sinus: The x~=nil check is to prevent a "the last call here returned buggy nils coming from Tourist:TransposeZoneCoordinate, so let's do the same silly thing" scenario.
  1356.                         return x, y, zone
  1357.                 end
  1358.                 last_px, last_py = px, py
  1359.                 if px == 0 or py == 0 or ((IsInInstance() or Cartographer:GetCurrentInstance()) and select(2, IsInInstance()) ~= "pvp") then
  1360.                         return x, y, zone
  1361.                 end
  1362.                 local pz = GetRealZoneText()
  1363.                 if Tourist:IsInstance(pz) then
  1364.                         px, py, pz = Tourist:GetBestZoneCoordinate(px, py, Cartographer:GetCurrentLocalizedZoneName())
  1365.                 else
  1366.                         px, py = Tourist:TransposeZoneCoordinate(px, py, Cartographer:GetCurrentLocalizedZoneName(), pz)
  1367.                 end
  1368.                 if px and py then
  1369.                         x, y, zone = px, py, BZR[pz]
  1370.                 end
  1371.  
  1372.                 return x, y, zone
  1373.         end
  1374. end
  1375.  
  1376. function Cartographer:PointToYards(x, y, zone)
  1377.         local w, h
  1378.         if not zone or zone == GetRealZoneText() then
  1379.                 w, h = currentYardWidth, currentYardHeight
  1380.         else
  1381.                 w, h = Tourist:GetZoneYardSize(zone)
  1382.                 if not w then
  1383.                         w, h = 1000, 1000 * 2/3
  1384.                 end
  1385.         end
  1386.         if x then
  1387.                 return x * w, y * h
  1388.         end
  1389.         return nil, nil
  1390. end
  1391.  
  1392. function Cartographer:GetDistanceToPoint(x, y, zone, px, py, pzone)
  1393.         if not px then
  1394.                 px, py, pzone = self:GetCurrentPlayerPosition()
  1395.                 if pzone then
  1396.                         pzone = BZL[pzone]
  1397.                 end
  1398.         end
  1399.         if px == 0 or py == 0 or not px or not py then
  1400.                 return nil
  1401.         end
  1402.         if pzone and BZH[pzone] then
  1403.                 pzone = BZL[pzone]
  1404.         end
  1405.         if zone and BZH[zone] then
  1406.                 zone = BZL[zone]
  1407.         end
  1408.         if not zone then
  1409.                 zone = GetRealZoneText()
  1410.         end
  1411.         if not pzone then
  1412.                 pzone = zone
  1413.         end
  1414.         local dist = Tourist:GetYardDistance(zone, x, y, pzone, px, py)
  1415.         return dist
  1416. end
  1417.  
  1418. function Cartographer:configureYards()
  1419.         if not WorldMapFrame:IsShown() then
  1420.                 SetMapToCurrentZone()
  1421.         end
  1422.         currentYardWidth, currentYardHeight = Tourist:GetZoneYardSize(GetRealZoneText())
  1423.         if not currentYardWidth then
  1424.                 currentYardWidth, currentYardHeight = 1000, 1000 * 2/3
  1425.         end
  1426. end
  1427. Cartographer.MINIMAP_ZONE_CHANGED = Cartographer.configureYards
  1428. function Cartographer:FullyInitialized()
  1429.         self:configureYards()
  1430.         self:PLAYER_LEVEL_UP()
  1431. end
  1432.  
  1433. function Cartographer:ZONE_CHANGED_NEW_AREA()
  1434.         if not WorldMapFrame:IsShown() then
  1435.                 SetMapToCurrentZone()
  1436.         end
  1437.         self:configureYards()
  1438. end