Repository navigation
Expand file tree
/
Copy pathInfoText.lua
More file actions
214 lines (189 loc) · 8.27 KB
/
Copy pathInfoText.lua
File metadata and controls
214 lines (189 loc) · 8.27 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
204
205
206
207
208
209
210
211
212
213
214
local addonName, ns = ...
local L = ns.L
local PADDING = 6
-- One-time hint next to the text, in the look of Blizzard's tutorial help tips, but compact.
local HINT_PADDING = 10
local HINT_LINE_SPACING = 3
local HINT_CLOSE_SIZE = 16
local HINT_DISTANCE = 20 -- gap between the text and the hint; the arrow sits in it
local HINT_ARROW_SIZE = 61 -- arrow frame as in HelpTip, the arrow texture is centered in it
local HINT_ARROW_OFFSET = -5
local HINT_ARROW_LEFT = 90 -- degrees; the arrow texture points down unrotated
local HINT_GLOW_OFFSET = -4 -- glow behind the arrow, HelpTip's offset for a left-pointing arrow
local InfoText = {}
ns.InfoText = InfoText
-- Top edge of a frame in UIParent coordinates (action bars can have their own scale).
local function TopInUIParent(frame)
local top = frame:GetTop()
return top and top * frame:GetEffectiveScale() / UIParent:GetEffectiveScale()
end
local function CenterXInUIParent(frame)
local x = frame:GetCenter()
return x and x * frame:GetEffectiveScale() / UIParent:GetEffectiveScale()
end
function InfoText:Init()
if self.frame then return end
local f = CreateFrame("Frame", "XPForeverInfoText", UIParent)
f:SetFrameStrata("MEDIUM")
f:SetClampedToScreen(true)
f:SetMovable(true)
f:RegisterForDrag("LeftButton")
self.frame = f
-- Highlight that only appears while Shift is held over the text, showing that it can be moved.
local dragBackground = f:CreateTexture(nil, "BACKGROUND")
dragBackground:SetAllPoints()
dragBackground:SetColorTexture(0.3, 0.6, 1, 0.25)
dragBackground:Hide()
self.dragBackground = dragBackground
local text = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
text:SetPoint("CENTER")
self.text = text
-- Move with Shift-drag; afterwards the position counts as "free".
f:SetScript("OnDragStart", function()
if not IsShiftKeyDown() then return end
self.isMoving = true
f:StartMoving()
end)
f:SetScript("OnDragStop", function()
if not self.isMoving then return end
f:StopMovingOrSizing()
-- We store the position ourselves; WoW's own layout cache would interfere.
f:SetUserPlaced(false)
self.isMoving = false
if self.moveHint then self.moveHint:Hide() end
local x, y = f:GetCenter()
XPForeverDB.infoPoint = { x = x, y = y }
ns.Options:SetValue("infoPosition", "free")
self:Anchor()
self:UpdateMouse()
end)
-- Shift-right-click: back to the automatic place above the action bars.
f:SetScript("OnMouseUp", function(_, button)
if button == "RightButton" and IsShiftKeyDown() then
XPForeverDB.infoPoint = nil
ns.Options:SetValue("infoPosition", "auto")
self:Anchor()
end
end)
f:SetScript("OnEnter", function()
self:UpdateMouse()
GameTooltip:SetOwner(f, "ANCHOR_TOP")
GameTooltip:SetText(ns.BrandLine())
GameTooltip:AddLine(ns.ClickHint("LeftButton", "SHIFT", L.actionDragMove, L.infoDragHint),
GRAY_FONT_COLOR:GetRGB())
GameTooltip:AddLine(ns.ClickHint("RightButton", "SHIFT", L.actionResetPosition, L.infoResetHint),
GRAY_FONT_COLOR:GetRGB())
GameTooltip:Show()
end)
f:SetScript("OnLeave", function()
GameTooltip_Hide()
self:UpdateMouse()
end)
-- Without Shift the text ignores the mouse (clicks and camera turning underneath work normally).
f:RegisterEvent("MODIFIER_STATE_CHANGED")
f:SetScript("OnEvent", function() self:UpdateMouse() end)
-- Action bars can move in Edit Mode.
EventRegistry:RegisterCallback("EditMode.Exit", function() self:Anchor() end, self)
end
-- Only accept the mouse while Shift is held. The move highlight appears only while the mouse is
-- over the text (or it is being dragged), not everywhere on the screen.
function InfoText:UpdateMouse()
local movable = IsShiftKeyDown() or self.isMoving
self.frame:EnableMouse(movable)
self.dragBackground:SetShown(self.isMoving or (movable and self.frame:IsMouseOver()))
if not movable and GameTooltip:GetOwner() == self.frame then
GameTooltip_Hide()
end
end
function InfoText:ApplySettings()
if not self.frame then return end
local font = self.text:GetFont()
self.text:SetFont(font, XPForeverDB.infoFontSize, "OUTLINE")
self.text:SetShadowOffset(0, 0)
self:UpdateMouse()
self:Anchor()
end
function InfoText:Anchor()
local f = self.frame
if not f or self.isMoving then return end
local db = XPForeverDB
f:ClearAllPoints()
if db.infoPosition == "free" and db.infoPoint then
f:SetPoint("CENTER", UIParent, "BOTTOMLEFT", db.infoPoint.x, db.infoPoint.y)
return
end
-- Automatic: above the highest visible bar of the bottom stack, centered on the experience bar.
local top, centerX
local bars = { ns.Bar.frame, MainActionBar, MultiBarBottomLeft, MultiBarBottomRight }
-- Blizzard containers holding e.g. the reputation bar (the XP container is covered by our bar).
for _, container in ipairs(StatusTrackingBarManager and StatusTrackingBarManager.barContainers or {}) do
table.insert(bars, container)
end
for _, bar in ipairs(bars) do
if bar and bar:IsShown() then
local barTop = TopInUIParent(bar)
if barTop and (not top or barTop > top) then top = barTop end
end
end
if ns.Bar.frame then centerX = CenterXInUIParent(ns.Bar.frame) end
if top and centerX then
f:SetPoint("BOTTOM", UIParent, "BOTTOMLEFT", centerX, top + db.infoOffset)
else
f:SetPoint("BOTTOM", UIParent, "BOTTOM", 0, 140)
end
end
-- Shown once (after the style choice on first start): points at the text and explains how to move it.
-- Our own frame instead of HelpTip:Show, so Blizzard's shared help tip pool stays untouched (taint).
-- Child of the text, so it hides along with it. Sits to the right: above the text there may be bars.
function InfoText:ShowMoveHintOnce()
local f = self.frame
if XPForeverDB.infoMoveHintSeen or not f or not f:IsShown() then return end
XPForeverDB.infoMoveHintSeen = true
local hint = CreateFrame("Frame", nil, f, "GlowBoxTemplate")
hint:SetFrameStrata("DIALOG")
hint:SetClampedToScreen(true)
hint:SetPoint("LEFT", f, "RIGHT", HINT_DISTANCE, 0)
hint:EnableMouse(true)
local text = hint:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
text:SetJustifyH("LEFT")
text:SetSpacing(HINT_LINE_SPACING)
text:SetPoint("TOPLEFT", HINT_PADDING, -HINT_PADDING)
text:SetText(table.concat({
NORMAL_FONT_COLOR:WrapTextInColorCode(L.infoMoveTip),
ns.ClickHint("LeftButton", "SHIFT", L.actionDragMove, L.infoDragHint),
ns.ClickHint("RightButton", "SHIFT", L.actionResetPosition, L.infoResetHint),
}, "\n"))
hint:SetSize(text:GetStringWidth() + HINT_PADDING * 2 + HINT_CLOSE_SIZE,
text:GetStringHeight() + HINT_PADDING * 2)
-- Blizzard's arrow template only centers the arrow in HelpTip's OnLoad, so do the same here.
local arrow = CreateFrame("Frame", nil, hint, "GlowBoxArrowTemplate")
arrow:SetSize(HINT_ARROW_SIZE, HINT_ARROW_SIZE)
arrow:SetPoint("CENTER", hint, "LEFT", HINT_ARROW_OFFSET, 0)
arrow.Arrow:ClearAllPoints()
arrow.Arrow:SetPoint("CENTER")
SetClampedTextureRotation(arrow.Arrow, HINT_ARROW_LEFT)
SetClampedTextureRotation(arrow.Glow, HINT_ARROW_LEFT)
arrow.Glow:ClearAllPoints()
arrow.Glow:SetPoint("CENTER", arrow.Arrow, "CENTER", HINT_GLOW_OFFSET, 0)
-- Small yellow X like on Blizzard's help tips.
local close = CreateFrame("Button", nil, hint)
close:SetSize(HINT_CLOSE_SIZE, HINT_CLOSE_SIZE)
close:SetPoint("TOPRIGHT", -3, -3)
close:SetNormalAtlas("common-icon-yellowx")
close:SetPushedAtlas("common-icon-yellowx-down")
close:SetHighlightAtlas("common-icon-yellowx", "ADD")
close:SetScript("OnClick", function() hint:Hide() end)
self.moveHint = hint
end
function InfoText:Refresh()
local f = self.frame
if not f then return end
local text = XPForeverDB.infoEnabled and ns.ShouldShow() and ns.BuildText("info") or ""
if text == "" then
f:Hide()
return
end
self.text:SetText(text)
f:SetSize(self.text:GetStringWidth() + PADDING * 2, self.text:GetStringHeight() + PADDING)
f:Show()
end