-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLauncher.lua
More file actions
203 lines (182 loc) · 7.15 KB
/
Copy pathLauncher.lua
File metadata and controls
203 lines (182 loc) · 7.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
-- WickCore
-- Launcher.lua — one Wick button, a data object per product.
--
-- Products register a launcher and get a LibDataBroker object when a broker
-- display is installed. Without one, WickCore draws a single minimap button
-- that opens a small hub listing every registered product.
local ADDON = ...
local Core = LibStub("WickCore-1.0", true)
if not Core or Core._sourceAddon ~= ADDON then return end
local Launcher = {}
Core.Launcher = Launcher
Launcher.entries = Launcher.entries or {}
local Chrome = Core.Chrome
-- The broker library is looked for when it is needed, not once as this
-- file loads: WickCore loads first, and the copy a player has may come
-- with an addon that loads after it (Wick's UI bundles one for its info
-- panels). Asked once at load, every Wick launcher went unpublished and
-- none could go in a broker slot.
local function broker() return LibStub("LibDataBroker-1.1", true) end
local function publish(entry)
if entry.ldb then return end
local LDB = broker()
if not LDB then return end
local addon, opts = entry.addon, entry.opts
local ok, obj = pcall(LDB.NewDataObject, LDB, addon.title, {
type = "launcher",
icon = opts.icon or Launcher.ICON,
label = addon.title,
text = opts.text,
OnClick = function(_, button)
if opts.onClick then Core.safe(opts.onClick, addon, button)
elseif addon.Toggle then Core.safe(addon.Toggle, addon) end
end,
OnTooltipShow = function(tt)
if opts.tooltip then Core.safe(opts.tooltip, tt, addon)
else tt:AddLine(Chrome:TitleMarkup(addon.title)) end
end,
})
if ok and obj then entry.ldb = obj end
end
-- Launchers registered before a broker library loaded get their feed once
-- every addon is in.
function Launcher:PublishBrokers()
for _, entry in pairs(self.entries) do publish(entry) end
end
local publisher = CreateFrame("Frame")
publisher:RegisterEvent("PLAYER_LOGIN")
publisher:SetScript("OnEvent", function() Launcher:PublishBrokers() end)
Launcher.ICON = "Interface\\Icons\\INV_Misc_Candle_03"
-- opts: { icon, onClick(button), tooltip(GameTooltip), text }
function Launcher:Register(addon, opts)
opts = opts or {}
local entry = { addon = addon, opts = opts }
self.entries[addon.name] = entry
publish(entry)
self:EnsureMinimapButton()
return entry
end
-- ============================================================
-- Minimap button (fallback when no broker display is present)
-- ============================================================
function Launcher:EnsureMinimapButton()
if self.button or not rawget(_G, "Minimap") then return end
local db = Core.self.db and Core.self.db.global.minimap or { angle = 220 }
self.db = db
local b = CreateFrame("Button", "WickCoreMinimapButton", Minimap)
b:SetSize(28, 28)
b:SetFrameStrata("MEDIUM")
b:SetFrameLevel(8)
b:RegisterForClicks("LeftButtonUp", "RightButtonUp")
b:RegisterForDrag("LeftButton")
b:SetMovable(true)
local bg = Chrome:Texture(b, "BACKGROUND", Chrome.Colors.void)
bg:SetPoint("TOPLEFT", 3, -3)
bg:SetPoint("BOTTOMRIGHT", -3, 3)
Chrome:AddBrackets(b)
local icon = b:CreateTexture(nil, "ARTWORK")
icon:SetTexture(self.ICON)
icon:SetPoint("TOPLEFT", 6, -6)
icon:SetPoint("BOTTOMRIGHT", -6, 6)
b.icon = icon
-- Round maps put the button on a circle just outside the edge; a square
-- map (a UI replacement says so through GetMinimapShape, as LibDBIcon
-- expects) puts it just inside the square's edge, at the same angle.
local function place()
local angle = math.rad(db.angle or 220)
local c, s = math.cos(angle), math.sin(angle)
local half = Minimap:GetWidth() / 2
local x, y
local shape = rawget(_G, "GetMinimapShape")
if shape and shape() == "SQUARE" then
local m = math.max(math.abs(c), math.abs(s))
local r = half - 16
x, y = c / m * r, s / m * r
else
x, y = c * (half + 6), s * (half + 6)
end
b:ClearAllPoints()
b:SetPoint("CENTER", Minimap, "CENTER", x, y)
end
self.PlaceMinimapButton = place
b:SetScript("OnDragStart", function(s)
s.dragging = true
s:SetScript("OnUpdate", function()
local mx, my = Minimap:GetCenter()
local cx, cy = GetCursorPosition()
local scale = Minimap:GetEffectiveScale()
cx, cy = cx / scale, cy / scale
db.angle = math.deg(math.atan2(cy - my, cx - mx))
place()
end)
end)
b:SetScript("OnDragStop", function(s)
s.dragging = false
s:SetScript("OnUpdate", nil)
end)
b:SetScript("OnClick", function(_, button)
if button == "RightButton" then
Core.Options:Open()
else
Launcher:ToggleHub()
end
end)
b:SetScript("OnEnter", function(s)
GameTooltip:SetOwner(s, "ANCHOR_LEFT")
local e = Launcher.entries.WickCore
if e and e.opts.tooltip then Core.safe(e.opts.tooltip, GameTooltip, Core.self) end
GameTooltip:Show()
end)
b:SetScript("OnLeave", function() GameTooltip:Hide() end)
place()
if db.hidden then b:Hide() end
self.button = b
end
function Launcher:SetMinimapHidden(hidden)
if self.db then self.db.hidden = hidden and true or false end
if self.button then
if hidden then self.button:Hide() else self.button:Show() end
end
end
-- ============================================================
-- Hub: every registered product, one row each
-- ============================================================
function Launcher:ToggleHub()
if not self.hub then
local p = Chrome:NewPanel("WickCoreHubFrame", { title = "Wick's Mods", width = 260, height = 120, strata = "DIALOG" })
p:ClearAllPoints()
if self.button then p:SetPoint("TOPRIGHT", self.button, "BOTTOMLEFT", 0, -4)
else p:SetPoint("CENTER") end
self.hub = p
end
local p = self.hub
if p:IsShown() then p:Hide() return end
-- Rebuild rows each open; the roster can change with LoadOnDemand.
if p.rows then for _, r in ipairs(p.rows) do r:Hide() end end
p.rows = {}
local y = 0
for name, entry in pairs(self.entries) do
if name ~= "WickCore" then
local row = Chrome:Button(p.content, Chrome:TitleMarkup(entry.addon.title), 240, 22)
row.label:ClearAllPoints()
row.label:SetPoint("LEFT", 8, 0)
row:SetPoint("TOPLEFT", 0, y)
row:SetScript("OnClick", function(_, button)
p:Hide()
if entry.opts.onClick then Core.safe(entry.opts.onClick, entry.addon, button)
elseif entry.addon.Toggle then Core.safe(entry.addon.Toggle, entry.addon) end
end)
p.rows[#p.rows + 1] = row
y = y - 26
end
end
if #p.rows == 0 then
local none = Chrome:Text(p.content, 11, Chrome.Colors.muted)
none:SetPoint("TOPLEFT", 4, -4)
none:SetText("No Wick addons registered yet.")
p.rows[1] = none
y = -26
end
p:SetHeight(Chrome.HEADER_H + 16 + (-y) + 8)
p:Show()
end