view FilterBar.lua @ 113:03e4a8b93012 v7.3.0-2

7.3 Updates - Added some map frame adjustments to keep the filter bar from obstructing edge of zone clicks KNOWN ISSUES: - Argus quests can only be filtered when viewing Argus maps - Main Argus map in the WorldMapFrame has misaligned pins; this is due to it using a different map texture from what is used in the teleporter map, so all the POI coordinates are based on that map in the client info
author Nenue
date Tue, 05 Sep 2017 03:14:34 -0400
parents b67ba1078824
children a4dfdd4f1cf3
line wrap: on
line source
-- WorldPlan
-- FilterBar.lua
-- Created: 10/27/2016 8:55 PM
-- %file-revision%
--
local _, db = ...
local print = DEVIAN_WORKSPACE and function(...) _G.print('FilterBar', ...) end or nop
local wprint = DEVIAN_WORKSPACE and function(...) _G.print('WP', ...) end or function() end
local wipe, ipairs, pairs = table.wipe, ipairs, pairs

local REWARD_CASH = WORLD_QUEST_REWARD_TYPE_FLAG_GOLD
local REWARD_ARTIFACT_POWER = WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER
local REWARD_GEAR = WORLD_QUEST_REWARD_TYPE_FLAG_EQUIPMENT
local REWARD_CURRENCY = WORLD_QUEST_REWARD_TYPE_FLAG_ORDER_RESOURCES
local REWARD_REAGENT = WORLD_QUEST_REWARD_TYPE_FLAG_MATERIALS


local filtersUsed
local filterFill = "Interface\\BUTTONS\\YELLOWORANGE64"
local filterMask = "Interface\\Minimap\\UI-Minimap-Background"

local HEADERS_SPACING = 3
local BUTTONS_SPACING = 1
local BUTTONS_HEIGHT = 20
local TOGGLE_SIZE = 20
local HEADERS_HEIGHT = 24

local LE_QUEST_TAG_TYPE_PVP = LE_QUEST_TAG_TYPE_PVP
local LE_QUEST_TAG_TYPE_PET_BATTLE = LE_QUEST_TAG_TYPE_PET_BATTLE
local LE_QUEST_TAG_TYPE_DUNGEON = LE_QUEST_TAG_TYPE_DUNGEON
local LE_QUEST_TAG_TYPE_PROFESSION = LE_QUEST_TAG_TYPE_PROFESSION

local barMouseOver
local filtersDirty = true
local layoutDirty = true
local matchesDirty -- don't flag until first filter loadout

local familiars = {
  [42159] = {npc = 106552, name = 'Nightwatcher Merayl'},
  [40277] = {npc = 97804, name = 'Tiffany Nelson'},
  [40298] = {npc = 99182, name = 'Sir Galveston'},
  [40282] = {npc=  99150, name = 'Grixis Tinypop'},
  [40278] = {npc = 98270, name = 'Robert Craig'},
  [48195] = {npc = 105250, name = 'Aulier'},
  [41990] = {npc = 105674, name = 'Varenne'},
  [41860] = {npc = 104970, name = 'Xorvasc'},
  [40299] = {npc = 99210, name = 'Bodhi Sunwayver'},
  [42442] = {npc = 107489, name = 'Amalia'},
  [40280] = {npc = 99077, name = 'Bredda Tenderhide'},
  [41687] = {npc = 104553, name = 'Odrogg'},
  [41944] = {npc = 105455, name = 'Trapper Jarrun'},
  [40337] = {npc = 97709, name = 'Master Tamer Flummox'},
  [40279] = {npc = 99035, name = 'Durian Strongfruit'}
}
local familiars_id = 9696

db.DefaultFilterType = {
  iconWidth = 24,
  iconHeight = 18,
  borderWidth = 3,
  highlightWidth = 2,
  TagSize = 12,
  TimeleftStage = 3,
  showNumber = true,
  numberFontObject = 'WorldPlanNumberFontThin'
}

local headerNames = {
  ['rewardType'] = 'Reward Type',
  ['worldQuestType'] = 'Quest Type',
  ['isElite'] = 'Elite',
  ['factionID'] = 'Bounties'
}

db.DefaultFilters = {
  { filterKey= 'rewardType', cVar = 'worldQuestFilterArtifactPower', filterValue = REWARD_ARTIFACT_POWER, label = 'Artifact Power', texture = "Interface\\ICONS\\inv_7xp_inscription_talenttome01" },
  { filterKey= 'rewardType', cVar = 'worldQuestFilterOrderResources', filterValue = REWARD_CURRENCY,label = 'Order Resources', texture = "Interface\\Icons\\inv_orderhall_orderresources" },
  { filterKey= 'rewardType', cVar = 'worldQuestFilterEquipment', filterValue = REWARD_GEAR, label = 'Equipment', texture = "Interface\\ICONS\\garrison_bluearmorupgrade" },
  { filterKey= 'rewardType', cVar = 'worldQuestFilterProfessionMaterials', filterValue = REWARD_REAGENT, label = 'Materials', texture = 1417744 },
  { filterKey= 'rewardType', cVar = 'worldQuestFilterGold', filterValue = REWARD_CASH, label = 'Gold', texture = "Interface\\Buttons\\UI-GroupLoot-Coin-Up" },
  { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PVP, label = 'PvP', texture = "Interface\\Icons\\Ability_PVP_GladiatorMedallion", spacing = 10 },
  { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PET_BATTLE, label = 'Pet Battle', texture = "Interface\\Icons\\PetJournalPortrait", },
  { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_DUNGEON, label = 'Dungeon', texture = "Interface\\LFGFRAME\\BattlenetWorking0", },
  { filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\ICONS\\70_professions_scroll_02", },
  --{ filterKey = 'isElite', filterValue = true, label = 'Elite', texture = "", desaturated = false},
  --{ filterKey = 'isElite', filterValue = false, label = 'Not-Elite', texture = "", desaturated = false},
}
local defaults = {}

WorldPlanSummaryMixin =  {
  fadeOpacity = 1,
}
local Module = WorldPlanSummaryMixin
Module.selectedBountyIndex = {}
Module.bounties = {}
Module.filterList = {}
Module.Buttons = {}
Module.Headers = {}
Module.cvarFiltersDirty = false
WorldPlanFilterButtonMixin = {}
local Pin = WorldPlanFilterButtonMixin

function Module:OnLoad()
  --self:SetParent(WorldMapFrame.UIElementsFrame)
  WorldPlan:AddHandler(self)
  --[[for index, info in ipairs(db.DefaultFilters) do
    info.zone = db.DefaultFilterType
    info.continent = db.DefaultFilterType
    info.pinMask =  "Interface\\Minimap\\UI-Minimap-Background"
    WorldPlan:AddTypeInfo(self,index, info)
  end
  --]]


end


function Module:OnEvent(event, arg)
  print('|cFF00FF88'..self:GetName()..':OnEvent()', event)
  if (event == 'QUEST_LOG_UPDATE') and arg then
    filtersDirty = true
    self:Refresh()
  end
end

local bountyIndex
local debug_headers = {}
local ToggleButton = {}
function Module:Setup()
  print('|cFF00FF88'..self:GetName()..':Setup()')
  self.isStale = true
  self:SetParent(WorldMapFrame.UIElementsFrame)
  --self:SetPoint('BOTTOMLEFT')
  for k,v in pairs( ToggleButton) do
    self.Toggle:SetScript(k,v)
  end
  self.Toggle:SetSize(TOGGLE_SIZE, TOGGLE_SIZE)

end


function Module:OnUpdate(sinceLast)
  if self.isStale then
    print('|cFF00FF00pushing update')
    self:Refresh()
  end

  barMouseOver = self:IsMouseOver()
  self:UpdateAlpha(sinceLast, barMouseOver)
end

function Module:OnMapInfo(isBrokenIsle, isZoomedOut, mapAreaID, isNewMap, isMapOpen)
  print('|cFFFFFF00OnMapInfo()', isBrokenIsle, isZoomedOut, mapAreaID, isNewMap, isMapOpen)
  if not isBrokenIsle then
    self:SetShown(false)
  else
    self:SetShown(true)
    if isMapOpen then
      self:Refresh()
    else
      matchesDirty = true
      layoutDirty = true
    end
  end
end

function Module:OnShow()
  print('|cFF00FF88'..self:GetName()..':OnShow()')
  self:Refresh()
end

local IsBountyCriteria = function(poiFrame, questID)
  return IsQuestCriteriaForBounty(poiFrame.questID, questID)
end

local tinsert, GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID = tinsert, GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID

function Module:OnConfigUpdate()

  ToggleButton.OnShow(self.Toggle)
end

function Module:Reset()



  self:UpdateFilters('SUMMARY_RESET')
  self:UpdateMatches('SUMMARY_RESET')
  self:UpdateLayout('SUMMARY_RESET')
end

function Module:Refresh()
  self:UpdateFilters('SUMMARY_REFRESH')
  self:UpdateMatches('SUMMARY_REFRESH')
  self:UpdateLayout('SUMMARY_REFRESH')
end

local questResults = {{} }
db.FilterList = {}

function Module:UpdateFilters(event)

  print('|cFF00FFFF'..self:GetName()..':GetFilters()', event)

  wipe(db.FilterList)

  for index, info in ipairs(db.DefaultFilters) do
    info.used = true
    tinsert(db.FilterList, info)
  end
  self.bounties = db.Bounties
  self.BountyFilters = {}
  local numBounties = 0
  for index, data in ipairs(self.bounties) do
    if not IsQuestComplete(data.questID) then
      numBounties = numBounties + 1
      local info = self.BountyFilters[index]
      if not info then
        info  = {}
        self.BountyFilters[index] = info
        layoutDirty = true
      else
        if info.questID ~= data.questID then
          layoutDirty = true
        end
      end

      local questTitle = GetQuestLogTitle(GetQuestLogIndexByID(data.questID))
      info.used = true
      info.filterKey = 'factionID'
      info.filterFunc = IsBountyCriteria
      info.filterValue = data.questID
      info.label = questTitle
      info.texture = data.icon
      print('loading emissary', questTitle)

      tinsert(db.FilterList, info)
      --{ filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", },
    end
  end

  for i = numBounties + 1, #self.BountyFilters do
    self.BountyFilters[i].used = nil
  end

end

function Module:UpdateMatches(event)
  print('|cFF00FF00UpdateMatches()', event)
  local quests = db.QuestsByID
  local questsForMap = db.QuestsByZone[db.currentMapID] or quests

  for index, info in ipairs(db.FilterList) do
    info.GlobalMatches = info.GlobalMatches or {}
    info.LocalMatches = info.LocalMatches or {}
    wipe(info.GlobalMatches)
    wipe(info.LocalMatches)
    print(info.filterKey, info.filterValue, info.filterFunc and 'func test' or 'compare')
    for questID, pin in pairs(quests) do
      print('', questID, pin.dataLoaded, (not IsQuestComplete(questID)))
      if pin.dataLoaded and (not IsQuestComplete(questID)) then
        local keyName, keyValue = info.filterKey, info.filterValue
        local isMatch
        if info.filterFunc then
          isMatch = info.filterFunc(pin, keyValue)
          print('  running special function, result =', isMatch)
        elseif pin[keyName] and (pin[keyName] == keyValue) then
          isMatch = true
          print('  rote match')
        end
        if isMatch then
          tinsert(info.GlobalMatches, pin)
          if questsForMap[questID] then
            print('  local map')
            tinsert(info.LocalMatches, pin)
          end
        end
      end
    end
    print('global', #info.GlobalMatches, 'local', #info.LocalMatches)
  end
end

function Module:UpdateLayout(event)
  print('|cFF00FF88UpdateLayout()|r', event, 'currentMap=',db.currentMapID)

  self.filtersSelected = nil

  local currentHeader
  local relativeFrame = self
  local lastKey

  local numHeaders = 0
  local numButtons = 0

  local layoutWidth = TOGGLE_SIZE + HEADERS_SPACING * 2
  local headerWidth = HEADERS_SPACING


  local layout = db.DefaultFilterType
  local borderWidth = layout.iconWidth + (layout.borderWidth * 2)
  local highlightWidth = borderWidth + (layout.highlightWidth * 2)
  local mapQuests = db.QuestsByZone[db.currentMapID] or db.QuestsByID
  local n = 0
  for _ in pairs(mapQuests) do
    n = n + 1
  end
  print(n, 'pins to work with')


  filtersUsed = nil
  local firstCvar, lastCvar
  local isFirst = true
  for index, info in ipairs(db.FilterList) do
    --print('num here', numQuestsHere, numQuestsTotal)


    --print(tostring(index).. ' ("'..tostring(info.label)..'" f('.. tostring(info.filterKey).. '='..tostring(info.filterValue) .. '), '..tostring(numQuests)..')')

    if #info.GlobalMatches >= 1 then
      if info.filterKey ~= lastKey then

        numHeaders = numHeaders + 1
        local nextHeader = self.Headers[numHeaders] or CreateFrame('Frame', 'FilterHeader' .. numHeaders, self,  'WorldPlanFilterHeader')
        if currentHeader then
          nextHeader:SetPoint('TOPLEFT', currentHeader, 'TOPRIGHT', 0, 0)

          currentHeader:SetSize(headerWidth - BUTTONS_SPACING + HEADERS_SPACING, HEADERS_HEIGHT)
          layoutWidth = layoutWidth + headerWidth
          headerWidth = HEADERS_SPACING
        else
          nextHeader:SetPoint('TOPLEFT', TOGGLE_SIZE + HEADERS_SPACING * 2, 0)

        end

        print('  begin header '..numHeaders, 'layout width =', floor(layoutWidth+.5))
        isFirst = true
        currentHeader = nextHeader
        currentHeader.Backdrop:SetHeight(BUTTONS_HEIGHT *2)
        currentHeader.Label:SetText(headerNames[info.filterKey])
        relativeFrame = currentHeader
      end

      numButtons = numButtons + 1
      local button = self.Buttons[numButtons]
      if not button then
        button = CreateFrame('Button', 'FilterButton'..numButtons, self, 'WorldPlanFilterButton')
        button:SetSize(32,BUTTONS_HEIGHT)
        button.icon:SetTexCoord(0.1,.9,.1,(1 * (BUTTONS_HEIGHT/32)))

        button.RewardBorder:ClearAllPoints()
        button.RewardBorder:SetPoint('TOPLEFT', button, 'TOPLEFT')
        button.RewardBorder:SetPoint('BOTTOMRIGHT', button, 'BOTTOMRIGHT')
      end

      button.info = info
      button.numQuestsTotal = #info.GlobalMatches
      button.numQuestsHere = #info.LocalMatches
      button.GlobalMatches = info.GlobalMatches
      button.LocalMatches = info.LocalMatches
      button.isFirst = isFirst
      button:SetID(index)
      button:SetParent(currentHeader)
      button.relativeFrame = relativeFrame
      button:Refresh()
      button:Show()
      relativeFrame = button
      headerWidth = headerWidth + button:GetWidth() + BUTTONS_SPACING

      isFirst = false
      if info.cVar then
        firstCvar = firstCvar or button
        lastCvar = button
      end
        lastKey = info.filterKey
    end
  end

  self.numHeaders = numHeaders
  for i = numButtons + 1, #self.Buttons do
    if self.Buttons[i] then
      self.Buttons[i]:Hide()
      wipe(self.Buttons[i].LocalMatches)
      wipe(self.Buttons[i].GlobalMatches)
    end
  end
  for i = numHeaders + 1, #self.Headers do
    if self.Headers[i] then
      self.Headers[i]:Hide()
    end
  end


  if currentHeader then
    currentHeader:SetSize(headerWidth - BUTTONS_SPACING + HEADERS_SPACING, HEADERS_HEIGHT)
    layoutWidth = layoutWidth + headerWidth + HEADERS_SPACING
  end

  self:SetSize(layoutWidth, BUTTONS_HEIGHT + (BUTTONS_SPACING * 2))
  self:ClearAllPoints()
  self:SetPoint('TOPLEFT', WorldMapFrameNavBar, 'BOTTOMLEFT', 0, -3)
  self.isStale = nil
  layoutDirty = nil
end

function Module:Cleanup()
  -- hide trailing buttons
end

local rgbWhite = {r = 1, g= 1, b= 1, hex = '|cFFFFFFFF' }
local found = {}
function Pin:OnEnter()
  if #self.GlobalMatches >= 1 then
    GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
    GameTooltip:AddLine(headerNames[self.info.filterKey])
    GameTooltip:AddLine(self.info.label)
    wipe(found)

    if self.numQuestsHere >= 1 then
      if self.numQuestsHere < self.numQuestsTotal then
        GameTooltip:AddLine('This Zone', 1, 1, 0)
      end
      for index, pin in ipairs(self.LocalMatches) do
        local colorInfo = (pin.quality and ITEM_QUALITY_COLORS[pin.quality]) or rgbWhite
        found[pin] = pin
        GameTooltip:AddLine('|T'.. tostring(pin.itemTexture)..':16:16|t ' .. tostring(pin.title) ..(pin.cheevos and " |cFFFFFF00!|R" or ''), 0, 1, 0)
      end
    end

    if self.numQuestsHere < self.numQuestsTotal then
      if self.numQuestsHere >= 1 then
        GameTooltip:AddLine(' ')
      end
      GameTooltip:AddLine('Other Maps', 1, 1, 0)
      for index, pin in ipairs(self.GlobalMatches) do
        if not found[pin] then
          local colorInfo = (pin.quality and ITEM_QUALITY_COLORS[pin.quality]) or rgbWhite
          found[pin] = pin
          GameTooltip:AddLine('|T'.. tostring(pin.itemTexture)..':16:16|t ' .. tostring(pin.title) ..(pin.cheevos and " |cFFFFFF00!|R" or ''), 1, 1, 1)
        end
      end
    end


    GameTooltip:AddLine(self.numQuestsTotal .. ' total')
    GameTooltip:Show()
  end
end

function Pin:OnLeave()
  if GameTooltip:IsOwned(self) then
    GameTooltip:Hide()
  end
end

function Pin:Refresh()
  local info = self.info
  self.filterKey = info.filterKey
  self.filterValue = info.filterValue
  self.tagID = info.tagID

  self.icon:SetTexture(info.texture)

  if (self.numQuestsHere == 0) and (self.numQuestsTotal >= 1) then
    self.count:SetText('*'..self.numQuestsTotal)
    self.count:SetTextColor(0,1,1)
  elseif self.numQuestsHere < self.numQuestsTotal then
    self.count:SetText(self.numQuestsHere..'+')
    self.count:SetTextColor(1,1,0)
  else
    self.count:SetText(self.numQuestsHere)
    self.count:SetTextColor(1,1,1)
  end

  self.cVar = info.cVar
  self.itemTexture = self.texture

  self:ClearAllPoints()
  if self.isFirst then
    self:SetPoint('TOPLEFT', self.relativeFrame, 'TOPLEFT', HEADERS_SPACING, -HEADERS_SPACING)
  else
    self:SetPoint('LEFT', self.relativeFrame, 'RIGHT', BUTTONS_SPACING, 0)
  end
  --print('anchor', self.relativeFrame:IsShown(), self:GetPoint(1))

  self.icon:SetDesaturated(self.numQuestsHere == 0)

  local r, g, b, a = 0,0,0,1
  local desaturated = false
  if (self.numQuestsHere > 0) or db.UsedFilters[self.filterKey] then

    if self.cVar then
      if GetCVarBool(self.cVar) then
        --self.count:SetTextColor(1,1,1)
        r,g,b,a = 0, 0, 0, 1
      else
        filtersUsed = true
        --self.count:SetTextColor(1,0,0)
        self.icon:SetDesaturated(true)
        r,g,b,a = 1, 0, 0, 0.5
      end
    else
      if db.UsedFilters[self.filterKey] then
        filtersUsed = true
        if db.UsedFilters[self.filterKey] == self.filterValue then
          --self.count:SetTextColor(0,1,0)
          r, g, b = 0, 1, 0
        else
          --self.count:SetTextColor(1,0,0)
          r, g, b = 1, 0, 0
        end
      else

        --self.count:SetTextColor(1,1,1)
        if self.filterKey == 'worldQuestType' then
          r, g, b = 0, 0, 1
        elseif self.filterKey == 'factionID' then
          r, g, b = 1, 1, 0
        end
      end
    end
  end
  self.RewardBorder:SetColorTexture(r, g, b)
  self:SetAlpha(a)

  --self:UpdateSize()
end

function Pin:OnLoad()
  self:RegisterForClicks('AnyUp')
  self:SetFrameStrata('HIGH')
  self:SetFrameLevel(151)
  self.questList = {}
  -- WORLD_MAP_UPDATE and PLAYER_ENTERING_WORLD are passed down from a higher level
end

function Pin:OnUpdate ()
  local group = self:GetParent()
  if group:IsMouseOver() and barMouseOver then
    group.Backdrop:Show()
    group.Label:Show()
  else
    group.Backdrop:Hide()
    group.Label:Hide()
  end
end

-- shift-click: reset filter
-- click: rotate through include(1), exclude(-1), ignore(nil)
local filtered_report = {}
local RESET_FILTER = "|cFFFFFFFF+%s|r"
local FILTER_EXCLUDE_TYPE = '|cFFFF0000-%s|r'
local FILTER_INCLUDE_TYPE = '|cFF00FF00+%s|r'
function Pin:OnClick (button)

  local filterKey = self.filterKey
  local filterValue = self.filterValue
  local cVar = self.cVar
  local parent = self:GetParent()
  local setDirty

  print('|cFF00FF88'..self:GetName()..':OnClick()|r', filterKey, filterValue, cVar, parent)

  local resetMode = (button == 'RightButton')
  wipe(filtered_report)
  if not (filterKey or cVar) then
    for i, info in ipairs(db.DefaultFilters) do
      if info.cVar then
        SetCVar(info.cVar, 1)
      elseif info.filterKey then
        if db.UsedFilters[info.filterKey] then
          db.UsedFilters[info.filterKey] = nil
        end
      end
    end
    parent.cvarFiltersDirty = false

    --WorldPlan:print('All filters reset.')
  elseif cVar then
    if resetMode then
      print('|cFFFF4400cleaning dirty')
      for i, info in ipairs(db.DefaultFilters) do
        if info.cVar then
          parent.cvarFiltersDirty = false
          SetCVar(info.cVar, 1)
        end
      end
      --WorldPlan:print('Reward filters reset.')
    elseif parent.cvarFiltersDirty == true then
      if GetCVarBool(cVar) then
        tinsert(filtered_report, FILTER_EXCLUDE_TYPE:format(tostring(self.info.label)))
        SetCVar(cVar, 0)
      else

        tinsert(filtered_report, FILTER_INCLUDE_TYPE:format(tostring(self.info.label)))
        SetCVar(cVar, 1)
      end

      -- check the visible filters and consider it clean if they're all lit
      parent.cvarFiltersDirty = false
      for i, info in ipairs(db.FilterList) do
        if info.cVar and (#info.GlobalMatches >= 1) then
          print(info.cVar, GetCVarBool(info.cVar))
          if GetCVarBool(info.cVar) == false then
            parent.cvarFiltersDirty = true
            print('|cFFFF4400still dirty')
            break
          end
        end
      end
    else
      print('|cFFFF4400making dirty')
      for i, info in ipairs(db.DefaultFilters) do
        if info.cVar then
          local msgType = (cVar == info.cVar) and FILTER_INCLUDE_TYPE or FILTER_EXCLUDE_TYPE
          SetCVar(info.cVar, ((cVar == info.cVar) and 1) or 0)
          tinsert(filtered_report, msgType:format(info.label))
        end
      end
      parent.cvarFiltersDirty = true
    end
  else
    if resetMode then
      wipe(db.UsedFilters)
      --WorldPlan:print('Type filters reset.')
    else
      if (db.UsedFilters[filterKey] == filterValue) or resetMode then
        db.UsedFilters[filterKey] = nil
        tinsert(filtered_report,  FILTER_INCLUDE_TYPE:format(tostring(filterKey)))
      else
        db.UsedFilters[filterKey] = filterValue
        tinsert(filtered_report,  FILTER_EXCLUDE_TYPE:format(tostring(filterKey)))
      end
    end
  end
  if #filtered_report >= 1 then
    --WorldPlan:print('Setting filter(s):', table.concat(filtered_report, ', '))
  end
  WorldPlan:Refresh(true)
end
function ToggleButton:OnEnter()

  GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
  GameTooltip:AddLine('Toggle Pins')
  GameTooltip:Show()
end
function ToggleButton:OnLeave()

  if GameTooltip:IsOwned(self) then
    GameTooltip:Hide()
  end
end
function ToggleButton:OnShow()
  self:SetChecked(db.Config.EnablePins and true or false)
end
function ToggleButton:OnHide()
  if GameTooltip:IsOwned(self) then
    GameTooltip:Hide()
  end

end
function ToggleButton:OnClick()
  --print(self:GetChecked())
  db.Config.EnablePins = self:GetChecked()
  _G.WorldPlan:OnConfigUpdate()
end