diff FilterBar.lua @ 93:98b5e08b75ed v1.4.9

- Fixed quest completion checking and handling - Changed animation method to hopefully stop weird flickering. - Pins are now visible before full reward data is loaded - Filter bar redesigned: - aligned horizontally along the top of the map display - filter buttons display a '+' when there are matches in both current and other zones, and '*' when there only matches in other zones - button tooltips separate local and global quests - button categories are highlighted and labeled when the cursor is over them - Fixed invalid POI targets appearing when the spell targeting cursor is active
author Nenue
date Sat, 15 Apr 2017 11:04:54 -0400
parents a12f782571c5
children b29b35cb8539
line wrap: on
line diff
--- a/FilterBar.lua	Tue Apr 11 00:44:22 2017 -0400
+++ b/FilterBar.lua	Sat Apr 15 11:04:54 2017 -0400
@@ -15,11 +15,26 @@
 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 = 40
+
 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'},
@@ -49,8 +64,15 @@
   showNumber = true,
   numberFontObject = 'WorldPlanNumberFontThin'
 }
+
+local headerNames = {
+  ['rewardType'] = 'Reward Type',
+  ['worldQuestType'] = 'Quest Type',
+  ['isElite'] = 'Elite',
+  ['factionID'] = 'Bounties'
+}
+
 db.DefaultFilters = {
-  { label = 'Filters', texture = "Interface\\WorldMap\\WorldMap-Icon" },
   { 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" },
@@ -58,8 +80,10 @@
   { 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\\UI-LFR-PORTRAIT", },
+  { 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 = {}
 
@@ -68,15 +92,14 @@
 Module.selectedBountyIndex = {}
 Module.bounties = {}
 Module.filterList = {}
-Module.buttons = {}
+Module.Buttons = {}
+Module.Headers = {}
 Module.cvarFiltersDirty = false
-WorldPlanFilterPinMixin = {}
-local Pin = WorldPlanFilterPinMixin
+WorldPlanFilterButtonMixin = {}
+local Pin = WorldPlanFilterButtonMixin
 
 function Module:OnLoad()
-  self:SetParent(WorldMapFrame.UIElementsFrame)
-  self:ClearAllPoints()
-  self:SetPoint('TOPRIGHT')
+  --self:SetParent(WorldMapFrame.UIElementsFrame)
   WorldPlan:AddHandler(self)
   --[[for index, info in ipairs(db.DefaultFilters) do
     info.zone = db.DefaultFilterType
@@ -85,37 +108,65 @@
     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
-    if db.QuestsByID[arg] then
-      if db.QuestsByID[arg].factionID then
-
-      end
-    end
+    filtersDirty = true
+    self:Refresh()
   end
-
-  self.isStale = true
 end
 
 local bountyIndex
 local debug_headers = {}
-
+local ToggleButton = {}
 function Module:Setup()
   print('|cFF00FF88'..self:GetName()..':Setup()')
   self.isStale = true
-  self:SetShown(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()
+function Module:OnUpdate(sinceLast)
   if self.isStale then
-    wprint('|cFF00FF00pushing update')
+    print('|cFF00FF00pushing update')
     self:Refresh()
   end
+
+  barMouseOver = self:IsMouseOver()
+  if barMouseOver or filtersUsed then
+
+    self.toAlpha = 1
+    self.Backdrop:Show()
+  else
+    self.toAlpha = 0.25
+    self.Backdrop:Hide()
+  end
+  local cAlpha = self:GetAlpha()
+  if cAlpha ~= self.toAlpha then
+    if cAlpha > self.toAlpha then
+      cAlpha = cAlpha - sinceLast*4
+      if cAlpha <= self.toAlpha then
+        cAlpha = self.toAlpha
+      end
+    else
+      cAlpha = cAlpha + sinceLast*4
+      if cAlpha >= self.toAlpha then
+        cAlpha = self.toAlpha
+      end
+    end
+  end
+  self:SetAlpha(cAlpha)
 end
 
 function Module:OnMapInfo(isBrokenIsle, isZoomedOut, mapAreaID, isNewMap, isMapOpen)
@@ -123,72 +174,142 @@
   if not isBrokenIsle then
     self:SetShown(false)
   else
-    if self:IsShown() then
+    self:SetShown(true)
+    if isMapOpen then
       self:Refresh()
+    else
+      matchesDirty = true
+      layoutDirty = true
     end
-    self:SetShown(true)
   end
 end
 
 function Module:OnShow()
   print('|cFF00FF88'..self:GetName()..':OnShow()')
-  if self.isStale then
-    self:Refresh()
+  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
+    tinsert(db.FilterList, info)
+  end
+  self.bounties = db.Bounties
+  self.BountyFilters = {}
+  for index, data in ipairs(self.bounties) do
+    if not IsQuestComplete(data.questID) then
+
+      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.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
 end
 
-local tinsert, GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID = tinsert, GetQuestBountyInfoForMapID, GetQuestLogTitle, GetQuestLogIndexByID
-function Module:GetFilters()
+function Module:UpdateMatches(event)
+  print('|cFF00FF00UpdateMatches()', event)
+  local quests = db.QuestsByID
+  local questsForMap = db.QuestsByZone[db.currentMapID] or quests
 
-  print('|cFF00FFFF'..self:GetName()..':GetFilters()')
+  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
 
-  wipe(self.filterList)
+        local keyName, keyValue = info.filterKey, info.filterValue
+        local isMatch
+        if info.filterFunc then
 
-  for index, info in ipairs(db.DefaultFilters) do
-    tinsert(self.filterList, info)
-  end
-  self.bounties, self.numBounties = GetQuestBountyInfoForMapID(db.currentMapID)
-  self.BountyFilters = {}
-  for index, data in ipairs(self.bounties) do
-    local info = self.BountyFilters[index]
-    if not info then
-      info  = {}
-      self.BountyFilters[index] = info
+          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
-
-    local questTitle = GetQuestLogTitle(GetQuestLogIndexByID(data.questID))
-
-    info.filterKey = 'factionID'
-    info.filterValue = data.factionID
-    info.label = questTitle
-    info.texture = data.icon
-    print('loading emissary', questTitle)
-
-    tinsert(self.filterList, info)
-    --{ filterKey= 'worldQuestType', filterValue = LE_QUEST_TAG_TYPE_PROFESSION, label = 'Profession', texture = "Interface\\LFGFRAME\\UI-LFR-PORTRAIT", },
+    print('global', #info.GlobalMatches, 'local', #info.LocalMatches)
   end
 end
 
-function Module:Reset()
-  self:GetFilters()
-end
+function Module:UpdateLayout(event)
+  print('|cFF00FF88UpdateLayout()|r', event, 'currentMap=',db.currentMapID)
 
-function Module:Refresh()
-  self:GetFilters()
-  self:Update()
-end
+  self.filtersSelected = nil
 
-local filterFill = "Interface\\BUTTONS\\YELLOWORANGE64"
-local filterMask = "Interface\\Minimap\\UI-Minimap-Background"
+  local currentHeader
+  local relativeFrame = self
+  local lastKey
 
-local questResults = {{}}
-function Module:Update()
-  local blocks = self.buttons
+  local numHeaders = 0
+  local numButtons = 0
 
-  local relativeFrame = self
-
-    local numHeaders = 0
-  print('|cFF00FF88'..self:GetName()..':Update()|r', 'currentMap=',db.currentMapID)
+  local layoutWidth = TOGGLE_SIZE + HEADERS_SPACING * 2
+  local headerWidth = HEADERS_SPACING
 
 
   local layout = db.DefaultFilterType
@@ -201,104 +322,140 @@
   end
   print(n, 'pins to work with')
 
+
+  filtersUsed = nil
   local firstCvar, lastCvar
-  for index, info in ipairs(self.filterList) do
-    local numQuestsHere = 0
-    local numQuestsTotal = 0
-    info.questList = info.questList or {}
-    wipe(info.questList)
-    print(info.filterKey, info.filterValue)
+  local isFirst = true
+  for index, info in ipairs(db.FilterList) do
+    --print('num here', numQuestsHere, numQuestsTotal)
 
-    for questID, pin in pairs(db.QuestsByID) do
-      --print(pin.worldQuestType ~= LE_QUEST_TAG_TYPE_PROFESSION, (db.Config.ShowAllProfessionQuests or pin.isKnownProfession))
-      if pin.used then
-
-        print(pin.title, mapQuests[questID])
-        if (pin.worldQuestType ~= LE_QUEST_TAG_TYPE_PROFESSION) or (db.Config.ShowAllProfessionQuests or pin.isKnownProfession) then
-
-          if not info.filterKey then
-            if mapQuests[questID] then
-                numQuestsHere = numQuestsHere + 1
-            end
-            numQuestsTotal = numQuestsTotal + 1
-          elseif pin[info.filterKey] == info.filterValue then
-            if mapQuests[questID] then
-              numQuestsHere = numQuestsHere + 1
-              tinsert(info.questList, pin)
-            end
-            numQuestsTotal = numQuestsTotal + 1
-          end
-        end
-      end
-
-    end
-    --print('num here', numQuestsHere, numQuestsTotal)
-    info.totalQuests = numQuestsTotal
 
     --print(tostring(index).. ' ("'..tostring(info.label)..'" f('.. tostring(info.filterKey).. '='..tostring(info.filterValue) .. '), '..tostring(numQuests)..')')
 
-    if numQuestsTotal >= 1 then
-      numHeaders = numHeaders + 1
-      local button = blocks[numHeaders]
-      if not blocks[numHeaders] then
-        button = CreateFrame('Button', 'WorldPlanFilterButton'..numHeaders, self, 'WorldPlanFilterPin')
-        button:SetSize(32,20)
-        button.icon:SetTexCoord(0.1,.9,.1,(1 * (20/32)))
+    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')
-
-
-        blocks[numHeaders] = button
       end
 
       button.info = info
-      button.numQuestsTotal = numQuestsTotal
-      button.numQuestsHere = numQuestsHere
-      button.questList = info.questList
-      button.isFirst = (numHeaders == 1)
+      button.numQuestsTotal = #info.GlobalMatches
+      button.numQuestsHere = #info.LocalMatches
+      button.GlobalMatches = info.GlobalMatches
+      button.LocalMatches = info.LocalMatches
+      button.isFirst = isFirst
       button:SetID(index)
-      button.spacing = ((relativeFrame.cVar and (not info.cVar)) or (relativeFrame.filterKey ~= info.filterKey)) and 5 or 1
+      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 = numHeaders + 1, #blocks do
-    if blocks[i] then
-      blocks[i]:Hide()
-      wipe(blocks[i].questList)
+  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('TOP')
   self.isStale = nil
+  layoutDirty = nil
 end
 
 function Module:Cleanup()
   -- hide trailing buttons
 end
 
-local rgbWhite = {r = 1, g= 1, b= 1, hex = '|cFFFFFFFF'}
+local rgbWhite = {r = 1, g= 1, b= 1, hex = '|cFFFFFFFF' }
+local found = {}
 function Pin:OnEnter()
-  if #self.questList >= 1 then
-    GameTooltip:SetOwner(self, 'ANCHOR_LEFT')
+  if #self.GlobalMatches >= 1 then
+    GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
     GameTooltip:AddLine(self.info.label)
-    for index, pin in ipairs(self.questList) do
-      local colorInfo = (pin.quality and ITEM_QUALITY_COLORS[pin.quality]) or rgbWhite
-      GameTooltip:AddLine('|T'.. tostring(pin.itemTexture)..':16:16|t ' .. tostring(pin.title) ..(pin.cheevos and " |cFFFFFF00!|R" or ''), colorInfo.r, colorInfo.g, colorInfo.b)
+    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
@@ -317,46 +474,58 @@
   self.tagID = info.tagID
 
   self.icon:SetTexture(info.texture)
-  self.count:SetText(self.numQuestsHere)
+
+  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('TOPRIGHT', self.relativeFrame, 'TOPRIGHT', -5, -42)
+    self:SetPoint('TOPLEFT', self.relativeFrame, 'TOPLEFT', HEADERS_SPACING, -HEADERS_SPACING)
   else
-    self:SetPoint('TOPLEFT', self.relativeFrame, 'BOTTOMLEFT', 0, -(self.spacing or 0))
+    self:SetPoint('LEFT', self.relativeFrame, 'RIGHT', BUTTONS_SPACING, 0)
   end
-  print('anchor', self.relativeFrame:IsShown(), self:GetPoint(1))
+  --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) then
+  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)
+        --self.count:SetTextColor(1,1,1)
         r,g,b,a = 0, 0, 0, 1
       else
-        self:GetParent().cvarFiltersDirty = true
-        self.count:SetTextColor(1,0,0)
+        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)
+          --self.count:SetTextColor(0,1,0)
           r, g, b = 0, 1, 0
         else
-          self.count:SetTextColor(1,0,0)
+          --self.count:SetTextColor(1,0,0)
           r, g, b = 1, 0, 0
         end
       else
 
-        self.count:SetTextColor(1,1,1)
+        --self.count:SetTextColor(1,1,1)
         if self.filterKey == 'worldQuestType' then
           r, g, b = 0, 0, 1
         elseif self.filterKey == 'factionID' then
@@ -375,12 +544,19 @@
   self:RegisterForClicks('AnyUp')
   self:SetFrameStrata('HIGH')
   self:SetFrameLevel(151)
-  self:SetScript('OnUpdate', nil)
   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
@@ -436,8 +612,8 @@
 
       -- check the visible filters and consider it clean if they're all lit
       parent.cvarFiltersDirty = false
-      for i, info in ipairs(parent.filterList) do
-        if info.cVar and (#info.questList >= 1) then
+      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
@@ -475,4 +651,30 @@
     --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
\ No newline at end of file