annotate Libs/LibDBIcon-1.0/LibDBIcon-1.0.lua @ 11:371e14cd2feb

- major fixes with icons not showing correctly.
author Tercio
date Thu, 08 Dec 2016 13:01:40 -0200
parents fc346da3afd9
children 9ad7f3c634f1
rev   line source
tercio@0 1 --[[
tercio@0 2 Name: DBIcon-1.0
Tercio@11 3 Revision: $Rev: 56 $
tercio@0 4 Author(s): Rabbit (rabbit.magtheridon@gmail.com)
tercio@0 5 Description: Allows addons to register to recieve a lightweight minimap icon as an alternative to more heavy LDB displays.
tercio@0 6 Dependencies: LibStub
tercio@0 7 License: GPL v2 or later.
tercio@0 8 ]]
tercio@0 9
tercio@0 10 --[[
tercio@0 11 Copyright (C) 2008-2011 Rabbit
tercio@0 12
tercio@0 13 This program is free software; you can redistribute it and/or
tercio@0 14 modify it under the terms of the GNU General Public License
tercio@0 15 as published by the Free Software Foundation; either version 2
tercio@0 16 of the License, or (at your option) any later version.
tercio@0 17
tercio@0 18 This program is distributed in the hope that it will be useful,
tercio@0 19 but WITHOUT ANY WARRANTY; without even the implied warranty of
tercio@0 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
tercio@0 21 GNU General Public License for more details.
tercio@0 22
tercio@0 23 You should have received a copy of the GNU General Public License
tercio@0 24 along with this program; if not, write to the Free Software
tercio@0 25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
tercio@0 26 ]]
tercio@0 27
tercio@0 28 -----------------------------------------------------------------------
tercio@0 29 -- DBIcon-1.0
tercio@0 30 --
tercio@0 31 -- Disclaimer: Most of this code was ripped from Barrel but fixed, streamlined
tercio@0 32 -- and cleaned up a lot so that it no longer sucks.
tercio@0 33 --
tercio@0 34
tercio@0 35 local DBICON10 = "LibDBIcon-1.0"
Tercio@11 36 local DBICON10_MINOR = tonumber(("$Rev: 56 $"):match("(%d+)"))
tercio@0 37 if not LibStub then error(DBICON10 .. " requires LibStub.") end
tercio@0 38 local ldb = LibStub("LibDataBroker-1.1", true)
tercio@0 39 if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end
tercio@0 40 local lib = LibStub:NewLibrary(DBICON10, DBICON10_MINOR)
tercio@0 41 if not lib then return end
tercio@0 42
tercio@0 43 lib.disabled = lib.disabled or nil
tercio@0 44 lib.objects = lib.objects or {}
tercio@0 45 lib.callbackRegistered = lib.callbackRegistered or nil
tercio@0 46 lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib)
tercio@0 47 lib.notCreated = lib.notCreated or {}
tercio@0 48
tercio@0 49 function lib:IconCallback(event, name, key, value, dataobj)
tercio@0 50 if lib.objects[name] then
tercio@0 51 if key == "icon" then
tercio@0 52 lib.objects[name].icon:SetTexture(value)
tercio@0 53 elseif key == "iconCoords" then
tercio@0 54 lib.objects[name].icon:UpdateCoord()
tercio@0 55 elseif key == "iconR" then
tercio@0 56 local _, g, b = lib.objects[name].icon:GetVertexColor()
tercio@0 57 lib.objects[name].icon:SetVertexColor(value, g, b)
tercio@0 58 elseif key == "iconG" then
tercio@0 59 local r, _, b = lib.objects[name].icon:GetVertexColor()
tercio@0 60 lib.objects[name].icon:SetVertexColor(r, value, b)
tercio@0 61 elseif key == "iconB" then
tercio@0 62 local r, g = lib.objects[name].icon:GetVertexColor()
tercio@0 63 lib.objects[name].icon:SetVertexColor(r, g, value)
tercio@0 64 end
tercio@0 65 end
tercio@0 66 end
tercio@0 67 if not lib.callbackRegistered then
tercio@0 68 ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__icon", "IconCallback")
tercio@0 69 ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconCoords", "IconCallback")
tercio@0 70 ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconR", "IconCallback")
tercio@0 71 ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconG", "IconCallback")
tercio@0 72 ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconB", "IconCallback")
tercio@0 73 lib.callbackRegistered = true
tercio@0 74 end
tercio@0 75
tercio@0 76 -- Tooltip code ripped from StatBlockCore by Funkydude
tercio@0 77 local function getAnchors(frame)
tercio@0 78 local x, y = frame:GetCenter()
tercio@0 79 if not x or not y then return "CENTER" end
tercio@0 80 local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or ""
tercio@0 81 local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM"
tercio@0 82 return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf
tercio@0 83 end
tercio@0 84
tercio@0 85 local function onEnter(self)
tercio@0 86 if self.isMoving then return end
tercio@0 87 local obj = self.dataObject
tercio@0 88 if obj.OnTooltipShow then
tercio@0 89 GameTooltip:SetOwner(self, "ANCHOR_NONE")
tercio@0 90 GameTooltip:SetPoint(getAnchors(self))
tercio@0 91 obj.OnTooltipShow(GameTooltip)
tercio@0 92 GameTooltip:Show()
tercio@0 93 elseif obj.OnEnter then
tercio@0 94 obj.OnEnter(self)
tercio@0 95 end
tercio@0 96 end
tercio@0 97
tercio@0 98 local function onLeave(self)
tercio@0 99 local obj = self.dataObject
tercio@0 100 GameTooltip:Hide()
tercio@0 101 if obj.OnLeave then obj.OnLeave(self) end
tercio@0 102 end
tercio@0 103
tercio@0 104 --------------------------------------------------------------------------------
tercio@0 105
tercio@0 106 local onClick, onMouseUp, onMouseDown, onDragStart, onDragStop, onDragEnd, updatePosition
tercio@0 107
tercio@0 108 do
tercio@0 109 local minimapShapes = {
tercio@0 110 ["ROUND"] = {true, true, true, true},
tercio@0 111 ["SQUARE"] = {false, false, false, false},
tercio@0 112 ["CORNER-TOPLEFT"] = {false, false, false, true},
tercio@0 113 ["CORNER-TOPRIGHT"] = {false, false, true, false},
tercio@0 114 ["CORNER-BOTTOMLEFT"] = {false, true, false, false},
tercio@0 115 ["CORNER-BOTTOMRIGHT"] = {true, false, false, false},
tercio@0 116 ["SIDE-LEFT"] = {false, true, false, true},
tercio@0 117 ["SIDE-RIGHT"] = {true, false, true, false},
tercio@0 118 ["SIDE-TOP"] = {false, false, true, true},
tercio@0 119 ["SIDE-BOTTOM"] = {true, true, false, false},
tercio@0 120 ["TRICORNER-TOPLEFT"] = {false, true, true, true},
tercio@0 121 ["TRICORNER-TOPRIGHT"] = {true, false, true, true},
tercio@0 122 ["TRICORNER-BOTTOMLEFT"] = {true, true, false, true},
tercio@0 123 ["TRICORNER-BOTTOMRIGHT"] = {true, true, true, false},
tercio@0 124 }
tercio@0 125
tercio@0 126 function updatePosition(button)
tercio@0 127 local angle = math.rad(button.db and button.db.minimapPos or button.minimapPos or 225)
tercio@0 128 local x, y, q = math.cos(angle), math.sin(angle), 1
tercio@0 129 if x < 0 then q = q + 1 end
tercio@0 130 if y > 0 then q = q + 2 end
tercio@0 131 local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND"
tercio@0 132 local quadTable = minimapShapes[minimapShape]
tercio@0 133 if quadTable[q] then
tercio@0 134 x, y = x*80, y*80
tercio@0 135 else
tercio@0 136 local diagRadius = 103.13708498985 --math.sqrt(2*(80)^2)-10
tercio@0 137 x = math.max(-80, math.min(x*diagRadius, 80))
tercio@0 138 y = math.max(-80, math.min(y*diagRadius, 80))
tercio@0 139 end
tercio@0 140 button:SetPoint("CENTER", Minimap, "CENTER", x, y)
tercio@0 141 end
tercio@0 142 end
tercio@0 143
tercio@0 144 function onClick(self, b) if self.dataObject.OnClick then self.dataObject.OnClick(self, b) end end
tercio@0 145 function onMouseDown(self) self.isMouseDown = true; self.icon:UpdateCoord() end
tercio@0 146 function onMouseUp(self) self.isMouseDown = false; self.icon:UpdateCoord() end
tercio@0 147
tercio@0 148 do
tercio@0 149 local function onUpdate(self)
tercio@0 150 local mx, my = Minimap:GetCenter()
tercio@0 151 local px, py = GetCursorPosition()
tercio@0 152 local scale = Minimap:GetEffectiveScale()
tercio@0 153 px, py = px / scale, py / scale
tercio@0 154 if self.db then
tercio@0 155 self.db.minimapPos = math.deg(math.atan2(py - my, px - mx)) % 360
tercio@0 156 else
tercio@0 157 self.minimapPos = math.deg(math.atan2(py - my, px - mx)) % 360
tercio@0 158 end
tercio@0 159 updatePosition(self)
tercio@0 160 end
tercio@0 161
tercio@0 162 function onDragStart(self)
tercio@0 163 self:LockHighlight()
tercio@0 164 self.isMouseDown = true
tercio@0 165 self.icon:UpdateCoord()
tercio@0 166 self:SetScript("OnUpdate", onUpdate)
tercio@0 167 self.isMoving = true
tercio@0 168 GameTooltip:Hide()
tercio@0 169 end
tercio@0 170 end
tercio@0 171
tercio@0 172 function onDragStop(self)
tercio@0 173 self:SetScript("OnUpdate", nil)
tercio@0 174 self.isMouseDown = false
tercio@0 175 self.icon:UpdateCoord()
tercio@0 176 self:UnlockHighlight()
tercio@0 177 self.isMoving = nil
tercio@0 178 end
tercio@0 179
tercio@0 180 local defaultCoords = {0, 1, 0, 1}
tercio@0 181 local function updateCoord(self)
tercio@0 182 local coords = self:GetParent().dataObject.iconCoords or defaultCoords
tercio@0 183 local deltaX, deltaY = 0, 0
tercio@0 184 if not self:GetParent().isMouseDown then
tercio@0 185 deltaX = (coords[2] - coords[1]) * 0.05
tercio@0 186 deltaY = (coords[4] - coords[3]) * 0.05
tercio@0 187 end
tercio@0 188 self:SetTexCoord(coords[1] + deltaX, coords[2] - deltaX, coords[3] + deltaY, coords[4] - deltaY)
tercio@0 189 end
tercio@0 190
tercio@0 191 local function createButton(name, object, db)
tercio@0 192 local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap)
tercio@0 193 button.dataObject = object
tercio@0 194 button.db = db
tercio@0 195 button:SetFrameStrata("MEDIUM")
tercio@0 196 button:SetSize(31, 31)
tercio@0 197 button:SetFrameLevel(8)
tercio@0 198 button:RegisterForClicks("anyUp")
tercio@0 199 button:RegisterForDrag("LeftButton")
tercio@0 200 button:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
tercio@0 201 local overlay = button:CreateTexture(nil, "OVERLAY")
tercio@0 202 overlay:SetSize(53, 53)
tercio@0 203 overlay:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder")
tercio@0 204 overlay:SetPoint("TOPLEFT")
tercio@0 205 local background = button:CreateTexture(nil, "BACKGROUND")
tercio@0 206 background:SetSize(20, 20)
tercio@0 207 background:SetTexture("Interface\\Minimap\\UI-Minimap-Background")
tercio@0 208 background:SetPoint("TOPLEFT", 7, -5)
tercio@0 209 local icon = button:CreateTexture(nil, "ARTWORK")
tercio@0 210 icon:SetSize(17, 17)
tercio@0 211 icon:SetTexture(object.icon)
tercio@0 212 icon:SetPoint("TOPLEFT", 7, -6)
tercio@0 213 button.icon = icon
tercio@0 214 button.isMouseDown = false
tercio@0 215
tercio@0 216 local r, g, b = icon:GetVertexColor()
tercio@0 217 icon:SetVertexColor(object.iconR or r, object.iconG or g, object.iconB or b)
tercio@0 218
tercio@0 219 icon.UpdateCoord = updateCoord
tercio@0 220 icon:UpdateCoord()
tercio@0 221
tercio@0 222 button:SetScript("OnEnter", onEnter)
tercio@0 223 button:SetScript("OnLeave", onLeave)
tercio@0 224 button:SetScript("OnClick", onClick)
tercio@0 225 if not db or not db.lock then
tercio@0 226 button:SetScript("OnDragStart", onDragStart)
tercio@0 227 button:SetScript("OnDragStop", onDragStop)
tercio@0 228 end
tercio@0 229 button:SetScript("OnMouseDown", onMouseDown)
tercio@0 230 button:SetScript("OnMouseUp", onMouseUp)
tercio@0 231
tercio@0 232 lib.objects[name] = button
tercio@0 233
tercio@0 234 if lib.loggedIn then
tercio@0 235 updatePosition(button)
tercio@0 236 if not db or not db.hide then button:Show()
tercio@0 237 else button:Hide() end
tercio@0 238 end
tercio@0 239 lib.callbacks:Fire("LibDBIcon_IconCreated", button, name) -- Fire 'Icon Created' callback
tercio@0 240 end
tercio@0 241
tercio@0 242 -- We could use a metatable.__index on lib.objects, but then we'd create
tercio@0 243 -- the icons when checking things like :IsRegistered, which is not necessary.
tercio@0 244 local function check(name)
tercio@0 245 if lib.notCreated[name] then
tercio@0 246 createButton(name, lib.notCreated[name][1], lib.notCreated[name][2])
tercio@0 247 lib.notCreated[name] = nil
tercio@0 248 end
tercio@0 249 end
tercio@0 250
tercio@0 251 lib.loggedIn = lib.loggedIn or false
tercio@0 252 -- Wait a bit with the initial positioning to let any GetMinimapShape addons
tercio@0 253 -- load up.
tercio@0 254 if not lib.loggedIn then
tercio@0 255 local f = CreateFrame("Frame")
tercio@0 256 f:SetScript("OnEvent", function()
tercio@0 257 for _, object in pairs(lib.objects) do
tercio@0 258 updatePosition(object)
tercio@0 259 if not lib.disabled and (not object.db or not object.db.hide) then object:Show()
tercio@0 260 else object:Hide() end
tercio@0 261 end
tercio@0 262 lib.loggedIn = true
tercio@0 263 f:SetScript("OnEvent", nil)
tercio@0 264 f = nil
tercio@0 265 end)
tercio@0 266 f:RegisterEvent("PLAYER_LOGIN")
tercio@0 267 end
tercio@0 268
tercio@0 269 local function getDatabase(name)
tercio@0 270 return lib.notCreated[name] and lib.notCreated[name][2] or lib.objects[name].db
tercio@0 271 end
tercio@0 272
tercio@0 273 function lib:Register(name, object, db)
tercio@0 274 if not object.icon then error("Can't register LDB objects without icons set!") end
tercio@0 275 if lib.objects[name] or lib.notCreated[name] then error("Already registered, nubcake.") end
tercio@0 276 if not lib.disabled and (not db or not db.hide) then
tercio@0 277 createButton(name, object, db)
tercio@0 278 else
tercio@0 279 lib.notCreated[name] = {object, db}
tercio@0 280 end
tercio@0 281 end
tercio@0 282
tercio@0 283 function lib:Lock(name)
tercio@0 284 if not lib:IsRegistered(name) then return end
tercio@0 285 if lib.objects[name] then
tercio@0 286 lib.objects[name]:SetScript("OnDragStart", nil)
tercio@0 287 lib.objects[name]:SetScript("OnDragStop", nil)
tercio@0 288 end
tercio@0 289 local db = getDatabase(name)
tercio@0 290 if db then db.lock = true end
tercio@0 291 end
tercio@0 292
tercio@0 293 function lib:Unlock(name)
tercio@0 294 if not lib:IsRegistered(name) then return end
tercio@0 295 if lib.objects[name] then
tercio@0 296 lib.objects[name]:SetScript("OnDragStart", onDragStart)
tercio@0 297 lib.objects[name]:SetScript("OnDragStop", onDragStop)
tercio@0 298 end
tercio@0 299 local db = getDatabase(name)
tercio@0 300 if db then db.lock = nil end
tercio@0 301 end
tercio@0 302
tercio@0 303 function lib:Hide(name)
tercio@0 304 if not lib.objects[name] then return end
tercio@0 305 lib.objects[name]:Hide()
tercio@0 306 end
tercio@0 307 function lib:Show(name)
tercio@0 308 if lib.disabled then return end
tercio@0 309 check(name)
tercio@0 310 lib.objects[name]:Show()
tercio@0 311 updatePosition(lib.objects[name])
tercio@0 312 end
tercio@0 313 function lib:IsRegistered(name)
tercio@0 314 return (lib.objects[name] or lib.notCreated[name]) and true or false
tercio@0 315 end
tercio@0 316 function lib:Refresh(name, db)
tercio@0 317 if lib.disabled then return end
tercio@0 318 check(name)
tercio@0 319 local button = lib.objects[name]
tercio@0 320 if db then button.db = db end
tercio@0 321 updatePosition(button)
tercio@0 322 if not button.db or not button.db.hide then
tercio@0 323 button:Show()
tercio@0 324 else
tercio@0 325 button:Hide()
tercio@0 326 end
tercio@0 327 if not button.db or not button.db.lock then
tercio@0 328 button:SetScript("OnDragStart", onDragStart)
tercio@0 329 button:SetScript("OnDragStop", onDragStop)
tercio@0 330 else
tercio@0 331 button:SetScript("OnDragStart", nil)
tercio@0 332 button:SetScript("OnDragStop", nil)
tercio@0 333 end
tercio@0 334 end
tercio@0 335 function lib:GetMinimapButton(name)
tercio@0 336 return lib.objects[name]
tercio@0 337 end
tercio@0 338
tercio@0 339 function lib:EnableLibrary()
tercio@0 340 lib.disabled = nil
tercio@0 341 for name, object in pairs(lib.objects) do
tercio@0 342 if not object.db or not object.db.hide then
tercio@0 343 object:Show()
tercio@0 344 updatePosition(object)
tercio@0 345 end
tercio@0 346 end
tercio@0 347 for name, data in pairs(lib.notCreated) do
tercio@0 348 if not data.db or not data.db.hide then
tercio@0 349 createButton(name, data[1], data[2])
tercio@0 350 lib.notCreated[name] = nil
tercio@0 351 end
tercio@0 352 end
tercio@0 353 end
tercio@0 354
tercio@0 355 function lib:DisableLibrary()
tercio@0 356 lib.disabled = true
tercio@0 357 for name, object in pairs(lib.objects) do
tercio@0 358 object:Hide()
tercio@0 359 end
tercio@0 360 end
tercio@0 361