HelpTip.lua

HelpTip.lua (9.0.2.36294)
  1. --[[
  2. infoTable = {
  3. text, -- also acts as a key for various API, MUST BE SET
  4. textColor = HIGHLIGHT_FONT_COLOR,
  5. textJustifyH = "LEFT",
  6. buttonStyle = HelpTip.ButtonStyle.None -- button to close the helptip, or no button at all
  7. targetPoint = HelpTip.Point.BottomEdgeCenter, -- where at the parent/relativeRegion the helptip should point
  8. alignment = HelpTip.Alignment.Center, -- alignment of the helptip relative to the parent/relativeRegion (basically where the arrow is located)
  9. hideArrow = false, -- whether to hide the arrow
  10. offsetX = 0,
  11. offsetY = 0,
  12. cvar, cvarValue, -- cvar to set when closed by user or from HelpTip:Acknowledge()
  13. cvarBitfield, bitfieldFlag, -- cvarbitfield to set when closed by user or from HelpTip:Acknowledge()
  14. onHideCallback, callbackArg, -- callback whenever the helptip is closed: onHideCallback(acknowledged, callbackArg)
  15. onAcknowledgeCallback -- callback whenever the helptip is closed by the user clicking its button: onAcknowledgeCallback(callbackArg)
  16. checkCVars = false, -- on: helptip will only be shown if the cvar or cvarBitfield is not set
  17. autoEdgeFlipping = false, -- on: will flip helptip to opposite edge based on relative region's center vs helptip's center during OnUpdate
  18. autoHorizontalSlide = false, -- on: will change the alignment to fit helptip on screen during OnUpdate
  19. useParentStrata = false, -- whether to use parent framestrata
  20. system = "" -- reference string
  21. systemPriority = 0, -- if a system and a priority is specified, higher priority helptips will close another helptip in that system
  22. extraRightMarginPadding = 0, -- extra padding on the right side of the helptip
  23. }
  24. ]]--
  25. HelpTip = { };
  26. -- external use enums
  27. HelpTip.Point = {
  28. TopEdgeLeft = 1,
  29. TopEdgeCenter = 2,
  30. TopEdgeRight = 3,
  31. BottomEdgeLeft = 4,
  32. BottomEdgeCenter = 5,
  33. BottomEdgeRight = 6,
  34. RightEdgeTop = 7,
  35. RightEdgeCenter = 8,
  36. RightEdgeBottom = 9,
  37. LeftEdgeTop = 10,
  38. LeftEdgeCenter = 11,
  39. LeftEdgeBottom = 12,
  40. };
  41. HelpTip.Alignment = {
  42. Left = 1,
  43. Center = 2,
  44. Right = 3,
  45. -- Intentional re-use of indices, really just need 3 settings but 5 makes it easier to visualize
  46. Top = 1,
  47. Bottom = 3,
  48. };
  49. HelpTip.ButtonStyle = {
  50. None = 1,
  51. Close = 2,
  52. Okay = 3,
  53. GotIt = 4,
  54. Next = 5,
  55. };
  56. -- internal use enums
  57. HelpTip.ArrowRotation = {
  58. Down = 1,
  59. Left = 2,
  60. Up = 3,
  61. Right = 4,
  62. };
  63. -- data
  64. HelpTip.PointInfo = {
  65. [HelpTip.Point.TopEdgeLeft] = { arrowRotation = HelpTip.ArrowRotation.Down, relativeAnchor = "TOPLEFT", oppositePoint = HelpTip.Point.BottomEdgeLeft },
  66. [HelpTip.Point.TopEdgeCenter] = { arrowRotation = HelpTip.ArrowRotation.Down, relativeAnchor = "TOP", oppositePoint = HelpTip.Point.BottomEdgeCenter },
  67. [HelpTip.Point.TopEdgeRight] = { arrowRotation = HelpTip.ArrowRotation.Down, relativeAnchor = "TOPRIGHT", oppositePoint = HelpTip.Point.BottomEdgeRight },
  68. [HelpTip.Point.RightEdgeTop] = { arrowRotation = HelpTip.ArrowRotation.Left, relativeAnchor = "TOPRIGHT", oppositePoint = HelpTip.Point.LeftEdgeTop },
  69. [HelpTip.Point.RightEdgeCenter] = { arrowRotation = HelpTip.ArrowRotation.Left, relativeAnchor = "RIGHT", oppositePoint = HelpTip.Point.LeftEdgeCenter },
  70. [HelpTip.Point.RightEdgeBottom] = { arrowRotation = HelpTip.ArrowRotation.Left, relativeAnchor = "BOTTOMRIGHT",oppositePoint = HelpTip.Point.LeftEdgeBottom },
  71. [HelpTip.Point.BottomEdgeRight] = { arrowRotation = HelpTip.ArrowRotation.Up, relativeAnchor = "BOTTOMRIGHT",oppositePoint = HelpTip.Point.TopEdgeRight },
  72. [HelpTip.Point.BottomEdgeCenter]= { arrowRotation = HelpTip.ArrowRotation.Up, relativeAnchor = "BOTTOM", oppositePoint = HelpTip.Point.TopEdgeCenter },
  73. [HelpTip.Point.BottomEdgeLeft] = { arrowRotation = HelpTip.ArrowRotation.Up, relativeAnchor = "BOTTOMLEFT", oppositePoint = HelpTip.Point.TopEdgeLeft },
  74. [HelpTip.Point.LeftEdgeBottom] = { arrowRotation = HelpTip.ArrowRotation.Right, relativeAnchor = "BOTTOMLEFT", oppositePoint = HelpTip.Point.RightEdgeBottom },
  75. [HelpTip.Point.LeftEdgeCenter] = { arrowRotation = HelpTip.ArrowRotation.Right, relativeAnchor = "LEFT", oppositePoint = HelpTip.Point.RightEdgeCenter },
  76. [HelpTip.Point.LeftEdgeTop] = { arrowRotation = HelpTip.ArrowRotation.Right, relativeAnchor = "TOPLEFT", oppositePoint = HelpTip.Point.RightEdgeTop },
  77. };
  78. HelpTip.ArrowOffsets = {
  79. [HelpTip.Alignment.Center] = { 0, 5 };
  80. [HelpTip.Alignment.Left] = { 35, 5 };
  81. [HelpTip.Alignment.Right] = { -35, 5 };
  82. };
  83. HelpTip.ArrowGlowOffsets = { 0, 4 };
  84. HelpTip.DistanceOffsets = {
  85. [HelpTip.Alignment.Center] = { 0, -20 };
  86. [HelpTip.Alignment.Left] = { -35, -20 };
  87. [HelpTip.Alignment.Right] = { 35, -20 };
  88. };
  89. HelpTip.Rotations = {
  90. [HelpTip.ArrowRotation.Down] = { modOffsetX = 1, modOffsetY = -1, swapOffsets = false, degrees = 0, anchors = { "BOTTOMLEFT", "BOTTOM", "BOTTOMRIGHT" } },
  91. [HelpTip.ArrowRotation.Left] = { modOffsetX = -1, modOffsetY = -1, swapOffsets = true, degrees = 90, anchors = { "TOPLEFT", "LEFT", "BOTTOMLEFT" } },
  92. [HelpTip.ArrowRotation.Up] = { modOffsetX = 1, modOffsetY = 1, swapOffsets = false, degrees = 180, anchors = { "TOPLEFT", "TOP", "TOPRIGHT"} },
  93. [HelpTip.ArrowRotation.Right] = { modOffsetX = 1, modOffsetY = -1, swapOffsets = true, degrees = 270, anchors = { "TOPRIGHT", "RIGHT", "BOTTOMRIGHT" } },
  94. };
  95. HelpTip.Buttons = {
  96. [HelpTip.ButtonStyle.None] = { textWidthAdj = 0, heightAdj = 0, parentKey = nil },
  97. [HelpTip.ButtonStyle.Close] = { textWidthAdj = -6, heightAdj = 0, parentKey = "CloseButton" },
  98. [HelpTip.ButtonStyle.Okay] = { textWidthAdj = 0, heightAdj = 30, parentKey = "OkayButton", text = OKAY },
  99. [HelpTip.ButtonStyle.GotIt] = { textWidthAdj = 0, heightAdj = 30, parentKey = "OkayButton", text = HELP_TIP_BUTTON_GOT_IT },
  100. [HelpTip.ButtonStyle.Next] = { textWidthAdj = 0, heightAdj = 30, parentKey = "OkayButton", text = NEXT },
  101. };
  102. HelpTip.verticalPadding = 31;
  103. HelpTip.minimumHeight = 72;
  104. HelpTip.defaultTextWidth = 196;
  105. HelpTip.width = 226;
  106. HelpTip.halfWidth = HelpTip.width / 2;
  107. HelpTip.supressHelpTips = {};
  108. do
  109. local function HelpTipReset(framePool, frame)
  110. frame:ClearAllPoints();
  111. frame:Hide();
  112. frame:Reset();
  113. end
  114. HelpTip.framePool = CreateFramePool("FRAME", nil, "HelpTipTemplate", HelpTipReset);
  115. end
  116. function HelpTip:SetHelpTipsEnabled(flag, enabled)
  117. HelpTip.supressHelpTips[flag] = enabled or false;
  118. end
  119. function HelpTip:AreHelpTipsEnabled()
  120. for flagType, flagValue in pairs(self.supressHelpTips) do
  121. if not flagValue then
  122. return false;
  123. end
  124. end
  125. return true;
  126. end
  127. function HelpTip:Show(parent, info, relativeRegion)
  128. assert(info and info.text, "Invalid helptip info");
  129. assert((info.bitfieldFlag ~= nil and info.cvarBitfield ~= nil) or (info.bitfieldFlag == nil and info.cvarBitfield == nil));
  130. if not self:CanShow(info) then
  131. return false;
  132. end
  133. if self:IsShowing(parent, info.text) then
  134. return true;
  135. end
  136. local frame = self.framePool:Acquire();
  137. frame.width = HelpTip.width + (info.extraRightMarginPadding or 0);
  138. frame:SetWidth(frame.width);
  139. frame:Init(parent, info, relativeRegion or parent);
  140. frame:Show();
  141. return true;
  142. end
  143. function HelpTip:CanShow(info)
  144. if Kiosk.IsEnabled() then
  145. return false;
  146. end
  147. if not self:AreHelpTipsEnabled() then
  148. return false;
  149. end
  150. if info.checkCVars then
  151. if info.cvar then
  152. if GetCVar(info.cvar) ~= info.cvarValue then
  153. return false;
  154. end
  155. end
  156. if info.cvarBitfield then
  157. if GetCVarBitfield(info.cvarBitfield, info.bitfieldFlag) then
  158. return false;
  159. end
  160. end
  161. end
  162. -- priority
  163. if info.system and info.systemPriority then
  164. for frame in self.framePool:EnumerateActive() do
  165. if frame.info.system == info.system and frame.info.systemPriority then
  166. if info.systemPriority > frame.info.systemPriority then
  167. frame:Close();
  168. -- by design there can only be one such frame, no need to keep going
  169. break;
  170. else
  171. -- higher or equal priority is already shown
  172. return false;
  173. end
  174. end
  175. end
  176. end
  177. return true;
  178. end
  179. function HelpTip:ForceHideAll()
  180. self:SetHelpTipsEnabled("ForceHideAll", false);
  181. self.framePool:ReleaseAll();
  182. self:SetHelpTipsEnabled("ForceHideAll", true);
  183. end
  184. function HelpTip:HideAllSystem(system, text)
  185. local framesToClose = { };
  186. for frame in self.framePool:EnumerateActive() do
  187. if frame:MatchesSystem(system, text) then
  188. tinsert(framesToClose, frame);
  189. end
  190. end
  191. for i, frame in ipairs(framesToClose) do
  192. frame:Close();
  193. end
  194. end
  195. function HelpTip:HideAll(parent)
  196. local framesToClose = { };
  197. for frame in self.framePool:EnumerateActive() do
  198. if frame:Matches(parent) then
  199. tinsert(framesToClose, frame);
  200. end
  201. end
  202. for i, frame in ipairs(framesToClose) do
  203. frame:Close();
  204. end
  205. end
  206. function HelpTip:Hide(parent, text)
  207. for frame in self.framePool:EnumerateActive() do
  208. if frame:Matches(parent, text) then
  209. frame:Close();
  210. break;
  211. end
  212. end
  213. end
  214. function HelpTip:IsShowing(parent, text)
  215. for frame in self.framePool:EnumerateActive() do
  216. if frame:Matches(parent, text) then
  217. return true;
  218. end
  219. end
  220. return false;
  221. end
  222. function HelpTip:IsShowingAny(parent)
  223. for frame in self.framePool:EnumerateActive() do
  224. if frame:Matches(parent) then
  225. return true;
  226. end
  227. end
  228. return false;
  229. end
  230. function HelpTip:IsShowingAnyInSystem(system)
  231. for frame in self.framePool:EnumerateActive() do
  232. if frame.info.system == system then
  233. return true;
  234. end
  235. end
  236. return false;
  237. end
  238. function HelpTip:Acknowledge(parent, text)
  239. for frame in self.framePool:EnumerateActive() do
  240. if frame:Matches(parent, text) then
  241. frame:Acknowledge();
  242. break;
  243. end
  244. end
  245. end
  246. function HelpTip:AcknowledgeSystem(system, text)
  247. for frame in self.framePool:EnumerateActive() do
  248. if frame:MatchesSystem(system, text) then
  249. frame:Acknowledge();
  250. end
  251. end
  252. end
  253. function HelpTip:Release(helpTip)
  254. self.framePool:Release(helpTip);
  255. end
  256. function HelpTip:IsPointVertical(point)
  257. return point <= HelpTip.Point.BottomEdgeRight;
  258. end
  259. HelpTipTemplateMixin = { };
  260. local function TransformOffsetsForRotation(offsets, rotationInfo)
  261. local offsetX = offsets[1];
  262. local offsetY = offsets[2];
  263. if rotationInfo.swapOffsets then
  264. offsetX, offsetY = offsetY, offsetX;
  265. end
  266. offsetX = offsetX * rotationInfo.modOffsetX;
  267. offsetY = offsetY * rotationInfo.modOffsetY;
  268. return offsetX, offsetY;
  269. end
  270. function HelpTipTemplateMixin:OnLoad()
  271. self.Arrow.Arrow:ClearAllPoints();
  272. self.Arrow.Arrow:SetPoint("CENTER");
  273. self.Arrow.Glow:ClearAllPoints();
  274. self.acknowledged = false;
  275. end
  276. function HelpTipTemplateMixin:OnShow()
  277. self:RegisterEvent("UI_SCALE_CHANGED");
  278. self:RegisterEvent("DISPLAY_SIZE_CHANGED");
  279. end
  280. function HelpTipTemplateMixin:OnHide()
  281. self:UnregisterEvent("UI_SCALE_CHANGED");
  282. self:UnregisterEvent("DISPLAY_SIZE_CHANGED");
  283. local info = self.info;
  284. if info.onHideCallback then
  285. info.onHideCallback(self.acknowledged, info.callbackArg);
  286. end
  287. if self.acknowledged and info.onAcknowledgeCallback then
  288. info.onAcknowledgeCallback(info.callbackArg);
  289. end
  290. HelpTip:Release(self);
  291. end
  292. function HelpTipTemplateMixin:OnEvent()
  293. self:Layout();
  294. end
  295. -- this exists because OnHide can be deferred
  296. function HelpTipTemplateMixin:Close()
  297. self.closed = true;
  298. self:Hide();
  299. end
  300. function HelpTipTemplateMixin:OnUpdate()
  301. local rx, ry = self.relativeRegion:GetCenter();
  302. local targetPoint = self.info.targetPoint;
  303. local targetAlignment = self.info.alignment;
  304. if self.info.autoHorizontalSlide then
  305. -- check right edge first
  306. local rightEdge = UIParent:GetRight();
  307. local canFitOnRight = rx + self.width + HelpTip.ArrowOffsets[HelpTip.Alignment.Right][1] < rightEdge;
  308. if not canFitOnRight then
  309. if rx + HelpTip.halfWidth < rightEdge then
  310. targetAlignment = HelpTip.Alignment.Center;
  311. else
  312. targetAlignment = HelpTip.Alignment.Right;
  313. end
  314. else
  315. -- left edge
  316. local leftEdge = UIParent:GetLeft();
  317. local canFitOnLeft = rx - self.width + HelpTip.ArrowOffsets[HelpTip.Alignment.Left][1] > leftEdge;
  318. if not canFitOnLeft then
  319. if rx - HelpTip.halfWidth > leftEdge then
  320. targetAlignment = HelpTip.Alignment.Center;
  321. else
  322. targetAlignment = HelpTip.Alignment.Left;
  323. end
  324. end
  325. end
  326. end
  327. if self.info.autoEdgeFlipping then
  328. local ux, uy = UIParent:GetCenter();
  329. local useMin;
  330. if HelpTip:IsPointVertical(targetPoint) then
  331. useMin = ry <= uy;
  332. else
  333. useMin = rx <= ux;
  334. end
  335. if useMin then
  336. targetPoint = min(self.flippedTargetPoint, targetPoint);
  337. else
  338. targetPoint = max(self.flippedTargetPoint, targetPoint);
  339. end
  340. end
  341. self:AnchorAndRotate(targetPoint, targetAlignment);
  342. end
  343. function HelpTipTemplateMixin:Init(parent, info, relativeRegion)
  344. self:SetParent(parent);
  345. if info.useParentStrata then
  346. self:SetFrameLevel(9000);
  347. else
  348. self:SetFrameStrata("DIALOG");
  349. end
  350. self.info = info;
  351. self.relativeRegion = relativeRegion;
  352. if info.autoEdgeFlipping then
  353. local targetPoint = self:GetTargetPoint();
  354. local pointInfo = HelpTip.PointInfo[targetPoint];
  355. self.flippedTargetPoint = pointInfo.oppositePoint;
  356. self:SetScript("OnUpdate", function() self:OnUpdate(); end);
  357. end
  358. if info.autoHorizontalSlide then
  359. self:SetScript("OnUpdate", function() self:OnUpdate(); end);
  360. end
  361. self:AnchorAndRotate();
  362. self:Layout();
  363. end
  364. function HelpTipTemplateMixin:GetTargetPoint()
  365. return self.info.targetPoint or HelpTip.Point.BottomEdgeCenter;
  366. end
  367. function HelpTipTemplateMixin:GetAlignment()
  368. return self.info.alignment or HelpTip.Alignment.Center;
  369. end
  370. function HelpTipTemplateMixin:GetButtonInfo()
  371. local buttonStyle = self.info.buttonStyle or HelpTip.ButtonStyle.None;
  372. return HelpTip.Buttons[buttonStyle];
  373. end
  374. function HelpTipTemplateMixin:AnchorAndRotate(overrideTargetPoint, overrideAlignment)
  375. local baseTargetPoint = self:GetTargetPoint();
  376. local targetPoint = overrideTargetPoint or baseTargetPoint;
  377. local alignment = overrideAlignment or self:GetAlignment();
  378. if targetPoint == self.appliedTargetPoint and alignment == self.appliedAlignment then
  379. return;
  380. end
  381. local pointInfo = HelpTip.PointInfo[targetPoint];
  382. local rotationInfo = HelpTip.Rotations[pointInfo.arrowRotation];
  383. -- anchor
  384. local arrowAnchor = rotationInfo.anchors[alignment];
  385. local offsetX, offsetY = TransformOffsetsForRotation(HelpTip.DistanceOffsets[alignment], rotationInfo);
  386. local baseOffsetX = self.info.offsetX or 0;
  387. local baseOffsetY = self.info.offsetY or 0;
  388. if overrideTargetPoint and overrideTargetPoint ~= baseTargetPoint then
  389. if HelpTip:IsPointVertical(targetPoint) then
  390. baseOffsetY = -baseOffsetY;
  391. else
  392. baseOffsetX = -baseOffsetX;
  393. end
  394. end
  395. offsetX = offsetX + baseOffsetX;
  396. offsetY = offsetY + baseOffsetY;
  397. self:ClearAllPoints();
  398. self:SetPoint(arrowAnchor, self.relativeRegion, pointInfo.relativeAnchor, offsetX, offsetY);
  399. -- arrow
  400. if self.info.hideArrow then
  401. self.Arrow:Hide();
  402. else
  403. self.Arrow:Show();
  404. self:RotateArrow(pointInfo.arrowRotation);
  405. self:AnchorArrow(rotationInfo, alignment);
  406. end
  407. self.appliedAlignment = alignment;
  408. self.appliedTargetPoint = targetPoint;
  409. end
  410. function HelpTipTemplateMixin:Layout()
  411. local targetPoint = self:GetTargetPoint();
  412. local pointInfo = HelpTip.PointInfo[targetPoint];
  413. local buttonInfo = self:GetButtonInfo();
  414. -- starting defaults
  415. local textOffsetX = 15;
  416. local textOffsetY = 1;
  417. local textWidth = HelpTip.defaultTextWidth;
  418. local height = HelpTip.verticalPadding;
  419. -- button
  420. textWidth = textWidth + buttonInfo.textWidthAdj;
  421. textOffsetY = textOffsetY + buttonInfo.heightAdj / 2;
  422. height = height + buttonInfo.heightAdj;
  423. if buttonInfo.parentKey then
  424. self[buttonInfo.parentKey]:Show();
  425. if buttonInfo.text then
  426. self[buttonInfo.parentKey]:SetText(buttonInfo.text);
  427. end
  428. end
  429. -- set height based on the text
  430. self:ApplyText();
  431. self.Text:SetWidth(textWidth);
  432. self.Text:SetPoint("LEFT", textOffsetX, textOffsetY);
  433. height = height + self.Text:GetHeight();
  434. if pointInfo.arrowRotation == HelpTip.ArrowRotation.Left or pointInfo.arrowRotation == HelpTip.ArrowRotation.Right then
  435. height = max(height, HelpTip.minimumHeight);
  436. end
  437. self:SetHeight(height);
  438. end
  439. function HelpTipTemplateMixin:ApplyText()
  440. local info = self.info;
  441. self.Text:SetText(info.text);
  442. local color = info.textColor or HIGHLIGHT_FONT_COLOR;
  443. self.Text:SetTextColor(color:GetRGB());
  444. local justifyH = info.textJustifyH;
  445. if not justifyH then
  446. if self.Text:GetNumLines() == 1 then
  447. justifyH = "CENTER";
  448. else
  449. justifyH = "LEFT";
  450. end
  451. end
  452. self.Text:SetJustifyH(justifyH);
  453. end
  454. function HelpTipTemplateMixin:AnchorArrow(rotationInfo, alignment)
  455. local arrowAnchor = rotationInfo.anchors[alignment];
  456. local offsetX, offsetY = TransformOffsetsForRotation(HelpTip.ArrowOffsets[alignment], rotationInfo);
  457. self.Arrow:ClearAllPoints();
  458. self.Arrow:SetPoint("CENTER", self, arrowAnchor, offsetX, offsetY);
  459. end
  460. function HelpTipTemplateMixin:RotateArrow(rotation)
  461. if self.Arrow.rotation == rotation then
  462. return;
  463. end
  464. local rotationInfo = HelpTip.Rotations[rotation];
  465. SetClampedTextureRotation(self.Arrow.Arrow, rotationInfo.degrees);
  466. SetClampedTextureRotation(self.Arrow.Glow, rotationInfo.degrees);
  467. local offsetX, offsetY = TransformOffsetsForRotation(HelpTip.ArrowGlowOffsets, rotationInfo);
  468. self.Arrow.Glow:SetPoint("CENTER", self.Arrow.Arrow, "CENTER", offsetX, offsetY);
  469. self.Arrow.rotation = rotation;
  470. end
  471. function HelpTipTemplateMixin:Acknowledge()
  472. local info = self.info;
  473. if info.cvar then
  474. SetCVar(info.cvar, info.cvarValue);
  475. end
  476. if info.cvarBitfield then
  477. SetCVarBitfield(info.cvarBitfield, info.bitfieldFlag, true);
  478. end
  479. self.acknowledged = true;
  480. self:Close();
  481. end
  482. function HelpTipTemplateMixin:Reset()
  483. self.info = nil;
  484. self.relativeRegion = nil;
  485. self.closed = false;
  486. self.acknowledged = false;
  487. self.CloseButton:Hide();
  488. self.OkayButton:Hide();
  489. -- flippity flip settings
  490. self.appliedTargetPoint = nil;
  491. self.flippedTargetPoint = nil;
  492. self.appliedAlignment = nil;
  493. self:SetScript("OnUpdate", nil);
  494. end
  495. function HelpTipTemplateMixin:Matches(parent, text)
  496. if self.closed then
  497. return false;
  498. end
  499. local textMatched = not text or self.info.text == text;
  500. return textMatched and self:GetParent() == parent;
  501. end
  502. function HelpTipTemplateMixin:MatchesSystem(system, text)
  503. if self.closed then
  504. return false;
  505. end
  506. local textMatched = not text or self.info.text == text;
  507. return textMatched and self.info.system == system;
  508. end