Blizzard_UIWidgets/Blizzard_UIWidgetManager.lua

Blizzard_UIWidgets/Blizzard_UIWidgetManager.lua (9.1.5.40906; unchanged since 9.1.5.40871)
  1. local TIMER_UPDATE_FREQUENCY_SECONDS = 1;
  2. local WIDGET_DEBUG_TEXTURE_SHOW = false;
  3. local WIDGET_DEBUG_TEXTURE_COLOR = CreateColor(0.1, 1.0, 0.1, 0.6);
  4. local WIDGET_CONTAINER_DEBUG_TEXTURE_SHOW = false;
  5. local WIDGET_CONTAINER_DEBUG_TEXTURE_COLOR = CreateColor(1.0, 0.1, 0.1, 0.6);
  6. local WIDGET_DEBUG_CUSTOM_TEXTURE_COLOR = CreateColor(1.0, 1.0, 0.0, 0.6);
  7. UIWidgetHorizontalWidgetContainerMixin = {};
  8. function UIWidgetHorizontalWidgetContainerMixin:OnLoad()
  9. self.parentWidgetContainer = self:GetParent();
  10. self.childWidgets = {};
  11. end
  12. function UIWidgetHorizontalWidgetContainerMixin:ResetChildWidgets()
  13. for _, widgetFrame in ipairs(self.childWidgets) do
  14. widgetFrame:SetParent(self.parentWidgetContainer);
  15. end
  16. self.childWidgets = {};
  17. end
  18. function UIWidgetHorizontalWidgetContainerMixin:AddChildWidget(widgetFrame)
  19. table.insert(self.childWidgets, widgetFrame);
  20. widgetFrame:SetParent(self);
  21. end
  22. UIWidgetContainerMixin = {};
  23. local function ResetHorizontalWidgetContainer(framePool, frame)
  24. frame:ResetChildWidgets();
  25. FramePool_HideAndClearAnchors(framePool, frame);
  26. end
  27. function UIWidgetContainerMixin:OnLoad()
  28. self.widgetPools = CreateFramePoolCollection();
  29. self.horizontalRowContainerPool = CreateFramePool("FRAME", self, "UIWidgetHorizontalWidgetContainerTemplate", ResetHorizontalWidgetContainer);
  30. if WIDGET_CONTAINER_DEBUG_TEXTURE_SHOW then
  31. self._debugBGTex = self:CreateTexture()
  32. self._debugBGTex:SetColorTexture(WIDGET_CONTAINER_DEBUG_TEXTURE_COLOR:GetRGBA());
  33. self._debugBGTex:SetAllPoints(self);
  34. end
  35. end
  36. function UIWidgetContainerMixin:OnEvent(event, ...)
  37. if event == "UPDATE_ALL_UI_WIDGETS" then
  38. self:ProcessAllWidgets();
  39. elseif event == "UPDATE_UI_WIDGET" then
  40. local widgetInfo = ...;
  41. if (widgetInfo.widgetSetID == self.widgetSetID) and (not widgetInfo.unit or (widgetInfo.unit == self.attachedToUnit)) then
  42. self:ProcessWidget(widgetInfo.widgetID, widgetInfo.widgetType);
  43. end
  44. end
  45. end
  46. function UIWidgetContainerMixin:OnUpdate(elapsed)
  47. -- Handle layout updates
  48. if self.dirtyLayout then
  49. self:UpdateWidgetLayout();
  50. end
  51. end
  52. function DefaultWidgetLayout(widgetContainerFrame, sortedWidgets)
  53. local horizontalRowContainer = nil;
  54. widgetContainerFrame.horizontalRowContainerPool:ReleaseAll();
  55. local widgetContainerFrameLevel = widgetContainerFrame:GetFrameLevel();
  56. local horizontalRowAnchorPoint = widgetContainerFrame.horizontalRowAnchorPoint or widgetContainerFrame.verticalAnchorPoint;
  57. local horizontalRowRelativePoint = widgetContainerFrame.horizontalRowRelativePoint or widgetContainerFrame.verticalRelativePoint;
  58. for index, widgetFrame in ipairs(sortedWidgets) do
  59. widgetFrame:ClearAllPoints();
  60. local widgetSetUsesVertical = widgetContainerFrame.widgetSetLayoutDirection == Enum.UIWidgetSetLayoutDirection.Vertical;
  61. local widgetUsesVertical = widgetFrame.layoutDirection == Enum.UIWidgetLayoutDirection.Vertical;
  62. local useOverlapLayout = widgetFrame.layoutDirection == Enum.UIWidgetLayoutDirection.Overlap;
  63. local useVerticalLayout = widgetUsesVertical or (widgetFrame.layoutDirection == Enum.UIWidgetLayoutDirection.Default and widgetSetUsesVertical);
  64. if useOverlapLayout then
  65. -- This widget uses overlap layout
  66. if index == 1 then
  67. -- But this is the first widget in the set, so just anchor it to the widget container
  68. if widgetSetUsesVertical then
  69. widgetFrame:SetPoint(widgetContainerFrame.verticalAnchorPoint, widgetContainerFrame);
  70. else
  71. widgetFrame:SetPoint(widgetContainerFrame.horizontalAnchorPoint, widgetContainerFrame);
  72. end
  73. else
  74. -- This is not the first widget in the set, so anchor it so it overlaps the previous widget
  75. local relative = sortedWidgets[index - 1];
  76. if widgetSetUsesVertical then
  77. -- Overlap it vertically
  78. widgetFrame:SetPoint(widgetContainerFrame.verticalAnchorPoint, relative, widgetContainerFrame.verticalAnchorPoint, 0, 0);
  79. else
  80. -- Overlap it horizontally
  81. widgetFrame:SetPoint(widgetContainerFrame.horizontalAnchorPoint, relative, widgetContainerFrame.horizontalAnchorPoint, 0, 0);
  82. end
  83. end
  84. widgetFrame:SetParent(widgetContainerFrame);
  85. widgetFrame:SetFrameLevel(widgetContainerFrameLevel + index);
  86. elseif useVerticalLayout then
  87. -- This widget uses vertical layout
  88. if index == 1 then
  89. -- This is the first widget in the set, so just anchor it to the widget container
  90. widgetFrame:SetPoint(widgetContainerFrame.verticalAnchorPoint, widgetContainerFrame);
  91. else
  92. -- This is not the first widget in the set, so anchor it to the previous widget (or the horizontalRowContainer if that exists)
  93. local relative = horizontalRowContainer or sortedWidgets[index - 1];
  94. widgetFrame:SetPoint(widgetContainerFrame.verticalAnchorPoint, relative, widgetContainerFrame.verticalRelativePoint, 0, widgetContainerFrame.verticalAnchorYOffset);
  95. if horizontalRowContainer then
  96. -- This widget is vertical, so horizontalRowContainer is done. Call layout on it and clear horizontalRowContainer
  97. horizontalRowContainer:Layout();
  98. horizontalRowContainer = nil;
  99. end
  100. end
  101. widgetFrame:SetParent(widgetContainerFrame);
  102. widgetFrame:SetFrameLevel(widgetContainerFrameLevel + index);
  103. else
  104. -- This widget uses horizontal layout
  105. local forceNewRow = widgetFrame.layoutDirection == Enum.UIWidgetLayoutDirection.HorizontalForceNewRow;
  106. local needNewRowContainer = not horizontalRowContainer or forceNewRow;
  107. if needNewRowContainer then
  108. -- We either don't have a horizontalRowContainer or this widget has requested a new row be started
  109. if horizontalRowContainer then
  110. horizontalRowContainer:Layout();
  111. end
  112. local newHorizontalRowContainer = widgetContainerFrame.horizontalRowContainerPool:Acquire();
  113. newHorizontalRowContainer:Show();
  114. if index == 1 then
  115. -- This is the first widget in the set, so just anchor it to the widget container
  116. newHorizontalRowContainer:SetPoint(widgetContainerFrame.verticalAnchorPoint, widgetContainerFrame, widgetContainerFrame.verticalAnchorPoint);
  117. else
  118. -- This is not the first widget in the set, so anchor it to the previous widget (or the horizontalRowContainer if that exists)
  119. local relative = horizontalRowContainer or sortedWidgets[index - 1];
  120. newHorizontalRowContainer:SetPoint(horizontalRowAnchorPoint, relative, horizontalRowRelativePoint, 0, widgetContainerFrame.verticalAnchorYOffset);
  121. end
  122. widgetFrame:SetPoint("TOPLEFT", newHorizontalRowContainer);
  123. newHorizontalRowContainer:AddChildWidget(widgetFrame);
  124. widgetFrame:SetFrameLevel(widgetContainerFrameLevel + index);
  125. -- The old horizontalRowContainer is no longer needed for anchoring, so set it to newHorizontalRowContainer
  126. horizontalRowContainer = newHorizontalRowContainer;
  127. else
  128. -- horizontalRowContainer already existed, so we just keep going in it, anchoring to the previous widget
  129. local relative = sortedWidgets[index - 1];
  130. horizontalRowContainer:AddChildWidget(widgetFrame);
  131. widgetFrame:SetFrameLevel(widgetContainerFrameLevel + index);
  132. widgetFrame:SetPoint(widgetContainerFrame.horizontalAnchorPoint, relative, widgetContainerFrame.horizontalRelativePoint, widgetContainerFrame.horizontalAnchorXOffset, 0);
  133. end
  134. end
  135. end
  136. if horizontalRowContainer then
  137. horizontalRowContainer:Layout();
  138. end
  139. widgetContainerFrame:Layout();
  140. end
  141. function UIWidgetContainerMixin:SetAttachedUnitAndType(attachedUnitInfo)
  142. if type(attachedUnitInfo) == "table" then
  143. self.attachedUnit = attachedUnitInfo.unit;
  144. self.attachedUnitIsGuid = attachedUnitInfo.isGuid;
  145. elseif attachedUnitInfo then
  146. self.attachedUnit = attachedUnitInfo;
  147. self.attachedUnitIsGuid = false;
  148. else
  149. self.attachedUnit = nil;
  150. self.attachedUnitIsGuid = nil;
  151. end
  152. end
  153. -- widgetLayoutFunction should take 2 arguments (this widget container and a sequence containing all widgetFrames belonging to that widgetSet, sorted by orderIndex). It can update the layout of the widgets & widgetContainer as it sees fit.
  154. -- IMPORTANT: widgetLayoutFunction is called every time any widget in this container is shown, hidden or re-ordered. If nil is passed DefaultWidgetLayout is used
  155. -- widgetInitFunction should take 1 argument (the widgetFrame). It should do anything needed for initialization of widgets by the registering system. It is called only once, when a widget is initialized (when entering a new map/area/subarea/phase)
  156. -- Either can be nil if your system doesn't need that functionaility
  157. -- attachedUnitInfo is only used if this widget container is attached to a particular unit (it is displayed in a nameplate or in the player choice UI), and causes UnitAura data sources to look at the attached unit
  158. --
  159. -- Calling RegisterForWidgetSet on a container that is already registered to a different WidgetSet will cause the old WidgetSet to get unregistered and the new one to take its place
  160. -- Calling RegisterForWidgetSet with a nil widgetSetID is the same as just calling UnregisterForWidgetSet
  161. function UIWidgetContainerMixin:RegisterForWidgetSet(widgetSetID, widgetLayoutFunction, widgetInitFunction, attachedUnitInfo)
  162. if self.widgetSetID then
  163. -- We are already registered to a WidgetSet
  164. if self.widgetSetID == widgetSetID then
  165. -- And it's the same WidgetSet we are trying to register again...nothing to do
  166. return;
  167. else
  168. -- We are already registered for a different WidgetSet...unregister it
  169. self:UnregisterForWidgetSet();
  170. end
  171. end
  172. if not widgetSetID then
  173. return;
  174. end
  175. local widgetSetInfo = C_UIWidgetManager.GetWidgetSetInfo(widgetSetID);
  176. if not widgetSetInfo then
  177. return;
  178. end
  179. self.widgetSetID = widgetSetID;
  180. self.layoutFunc = widgetLayoutFunction or DefaultWidgetLayout;
  181. self.initFunc = widgetInitFunction;
  182. self.widgetFrames = {};
  183. self.timerWidgets = {};
  184. self.numTimers = 0;
  185. self.numWidgetsShowing = 0;
  186. self:SetAttachedUnitAndType(attachedUnitInfo)
  187. self.widgetSetLayoutDirection = widgetSetInfo.layoutDirection;
  188. self.verticalAnchorYOffset = -widgetSetInfo.verticalPadding;
  189. if self.attachedUnit then
  190. C_UIWidgetManager.RegisterUnitForWidgetUpdates(self.attachedUnit, self.attachedUnitIsGuid);
  191. end
  192. self:ProcessAllWidgets();
  193. if self.showAndHideOnWidgetSetRegistration then
  194. self:Show();
  195. end
  196. self:RegisterEvent("UPDATE_ALL_UI_WIDGETS");
  197. self:RegisterEvent("UPDATE_UI_WIDGET");
  198. UIWidgetManager:OnWidgetContainerRegistered(self);
  199. end
  200. function UIWidgetContainerMixin:UnregisterForWidgetSet()
  201. if not self.widgetSetID then
  202. -- We are not registered to a WidgetSet...nothing to do
  203. return;
  204. end
  205. -- Remove all widgets from this widget container
  206. self:RemoveAllWidgets();
  207. self:UpdateWidgetLayout();
  208. -- And clear everything else
  209. self.widgetSetID = nil;
  210. self.layoutFunc = nil;
  211. self.initFunc = nil;
  212. self.dirtyLayout = nil;
  213. if self.showAndHideOnWidgetSetRegistration then
  214. self:Hide();
  215. end
  216. if self.attachedUnit then
  217. if UIWidgetManager.processingUnit == self.attachedUnit then
  218. UIWidgetManager.processingUnit = nil;
  219. end
  220. C_UIWidgetManager.UnregisterUnitForWidgetUpdates(self.attachedUnit, self.attachedUnitIsGuid);
  221. self:SetAttachedUnitAndType(nil);
  222. end
  223. self:UnregisterEvent("UPDATE_ALL_UI_WIDGETS");
  224. self:UnregisterEvent("UPDATE_UI_WIDGET");
  225. UIWidgetManager:OnWidgetContainerUnregistered(self);
  226. end
  227. function UIWidgetContainerMixin:RegisterTimerWidget(widgetID, widgetFrame)
  228. if not self.timerWidgets[widgetID] then
  229. -- New timer added
  230. self.timerWidgets[widgetID] = widgetFrame;
  231. if not self.ticker then
  232. self.ticker = C_Timer.NewTicker(TIMER_UPDATE_FREQUENCY_SECONDS,
  233. function()
  234. for id, widget in pairs(self.timerWidgets) do
  235. self:ProcessWidget(id, widget.widgetType);
  236. end
  237. end);
  238. end
  239. self.numTimers = self.numTimers + 1;
  240. end
  241. end
  242. function UIWidgetContainerMixin:UnregisterTimerWidget(widgetID)
  243. if self.timerWidgets[widgetID] then
  244. -- Existing timer removed
  245. self.timerWidgets[widgetID] = nil;
  246. self.numTimers = self.numTimers - 1;
  247. if self.numTimers == 0 and self.ticker then
  248. self.ticker:Cancel();
  249. self.ticker = nil;
  250. end
  251. end
  252. end
  253. function UIWidgetContainerMixin:GatherWidgetsByWidgetTag(widgetArray, widgetTag)
  254. for _, widgetFrame in pairs(self.widgetFrames) do
  255. if widgetTag == widgetFrame.widgetTag then
  256. table.insert(widgetArray, widgetFrame);
  257. end
  258. end
  259. end
  260. -- Mark all currently shown widgets to be removed
  261. function UIWidgetContainerMixin:MarkAllWidgetsForRemoval()
  262. for _, widgetFrame in pairs(self.widgetFrames) do
  263. widgetFrame.markedForRemove = true;
  264. end
  265. end
  266. -- Go through all widgets in this container and call AnimOut on any that are marked for removal. This will cause them to animate out and RemoveWidget will be called once that is done.
  267. function UIWidgetContainerMixin:AnimateOutAllMarkedWidgets()
  268. for _, widgetFrame in pairs(self.widgetFrames) do
  269. if widgetFrame.markedForRemove then
  270. widgetFrame:AnimOut();
  271. end
  272. end
  273. end
  274. -- Removes all widgets from this container immediately (don't animate them out)
  275. function UIWidgetContainerMixin:RemoveAllWidgets()
  276. self.widgetFrames = {};
  277. self.timerWidgets = {};
  278. self.numTimers = 0;
  279. self.numWidgetsShowing = 0;
  280. if self.ticker then
  281. self.ticker:Cancel();
  282. self.ticker = nil;
  283. end
  284. self.widgetPools:ReleaseAll();
  285. end
  286. -- This is called AFTER the widget is done animating out. The widgetFrame is actually released back to the pool and hidden.
  287. function UIWidgetContainerMixin:RemoveWidget(widgetID)
  288. local widgetFrame = self.widgetFrames[widgetID];
  289. if not widgetFrame then
  290. -- This widget was never created. Nothing to do
  291. return;
  292. end
  293. -- If this is a widget with a timer, remove it from the timer list
  294. if widgetFrame.hasTimer then
  295. self:UnregisterTimerWidget(widgetID);
  296. end
  297. self.widgetPools:Release(widgetFrame);
  298. self.widgetFrames[widgetID] = nil;
  299. -- The layout is dirty
  300. self.dirtyLayout = true;
  301. end
  302. local function ResetWidget(pool, widgetFrame)
  303. widgetFrame:OnReset();
  304. end
  305. function UIWidgetContainerMixin:GetWidgetFromPools(templateInfo)
  306. if templateInfo then
  307. self.widgetPools:CreatePoolIfNeeded(templateInfo.frameType, self, templateInfo.frameTemplate, ResetWidget);
  308. local widgetFrame = self.widgetPools:Acquire(templateInfo.frameTemplate);
  309. widgetFrame:SetParent(self);
  310. return widgetFrame;
  311. end
  312. end
  313. function UIWidgetContainerMixin:CreateWidget(widgetID, widgetType, widgetTypeInfo, widgetInfo)
  314. local widgetFrame = self:GetWidgetFromPools(widgetTypeInfo.templateInfo);
  315. widgetFrame.widgetID = widgetID;
  316. widgetFrame.widgetSetID = self.widgetSetID;
  317. widgetFrame.widgetType = widgetType;
  318. widgetFrame.hasTimer = widgetInfo.hasTimer;
  319. widgetFrame.orderIndex = widgetInfo.orderIndex;
  320. widgetFrame.widgetTag = widgetInfo.widgetTag;
  321. widgetFrame.inAnimType = widgetInfo.inAnimType;
  322. widgetFrame.outAnimType = widgetInfo.outAnimType;
  323. widgetFrame.layoutDirection = widgetInfo.layoutDirection;
  324. widgetFrame.modelSceneLayer = widgetInfo.modelSceneLayer;
  325. widgetFrame.scriptedAnimationEffectID = widgetInfo.scriptedAnimationEffectID;
  326. widgetFrame.markedForRemove = nil;
  327. -- If this is a widget with a timer, add it from the timer list
  328. if widgetFrame.hasTimer then
  329. self:RegisterTimerWidget(widgetID, widgetFrame);
  330. end
  331. -- If there is an init function, run it
  332. if self.initFunc then
  333. self.initFunc(widgetFrame);
  334. end
  335. self.widgetFrames[widgetID] = widgetFrame;
  336. return widgetFrame;
  337. end
  338. function UIWidgetContainerMixin:ProcessWidget(widgetID, widgetType)
  339. local widgetTypeInfo = UIWidgetManager:GetWidgetTypeInfo(widgetType);
  340. if not widgetTypeInfo then
  341. -- This WidgetType is not supported (nothing called RegisterWidgetVisTypeTemplate for it)
  342. return;
  343. end
  344. UIWidgetManager:UpdateProcessingUnit(self.attachedUnit, self.attachedUnitIsGuid);
  345. local widgetInfo = widgetTypeInfo.visInfoDataFunction(widgetID);
  346. local widgetFrame = self.widgetFrames[widgetID];
  347. local widgetAlreadyExisted = (widgetFrame ~= nil);
  348. local oldOrderIndex;
  349. local oldLayoutDirection;
  350. local isNewWidget = false;
  351. if widgetAlreadyExisted then
  352. -- Widget already existed
  353. if not widgetInfo then
  354. -- widgetInfo is nil, indicating it should no longer be shown...animate it out (RemoveWidget will be called once that is done)
  355. widgetFrame:AnimOut();
  356. widgetFrame.markedForRemove = nil;
  357. return;
  358. end
  359. -- Otherwise the widget should still show...save the current orderIndex and layoutDirection so we can determine if they change after Setup is run
  360. oldOrderIndex = widgetFrame.orderIndex;
  361. oldLayoutDirection = widgetFrame.layoutDirection;
  362. -- Remove markedForRemove because it is still showing
  363. widgetFrame.markedForRemove = nil;
  364. else
  365. -- Widget did not already exist
  366. if widgetInfo then
  367. -- And it should be shown...create it
  368. widgetFrame = self:CreateWidget(widgetID, widgetType, widgetTypeInfo, widgetInfo);
  369. isNewWidget = true;
  370. else
  371. -- Widget should not be shown. It didn't already exist so there is nothing to do
  372. return;
  373. end
  374. end
  375. -- Ok we are now SURE that this widget should be shown and we have a frame for it
  376. -- Run the Setup function on the widget (could change the orderIndex and/or layoutDirection)
  377. widgetFrame:Setup(widgetInfo, self);
  378. if(isNewWidget) then
  379. --Only Apply the effects when the widget is first added.
  380. widgetFrame:ApplyEffects(widgetInfo);
  381. end
  382. if WIDGET_DEBUG_TEXTURE_SHOW then
  383. if not widgetFrame._debugBGTex then
  384. widgetFrame._debugBGTex = widgetFrame:CreateTexture()
  385. widgetFrame._debugBGTex:SetColorTexture(WIDGET_DEBUG_TEXTURE_COLOR:GetRGBA());
  386. widgetFrame._debugBGTex:SetAllPoints(widgetFrame);
  387. end
  388. if widgetFrame.CustomDebugSetup then
  389. widgetFrame:CustomDebugSetup(WIDGET_DEBUG_CUSTOM_TEXTURE_COLOR);
  390. end
  391. end
  392. if isNewWidget and widgetFrame.OnAcquired then
  393. widgetFrame:OnAcquired(widgetInfo)
  394. end
  395. -- Determine if we need to run layout again
  396. local needsLayout = (oldOrderIndex ~= widgetFrame.orderIndex) or (oldLayoutDirection ~= widgetFrame.layoutDirection);
  397. if needsLayout then
  398. -- Either this is a new widget or either orderIndex or layoutDirection changed. In either case layout needs to be run
  399. self.dirtyLayout = true;
  400. end
  401. end
  402. function UIWidgetContainerMixin:ProcessAllWidgets()
  403. -- First mark all widgets for removal
  404. self:MarkAllWidgetsForRemoval();
  405. -- Add any new widgets and unmark any existing widgets that are still shown
  406. local setWidgets = C_UIWidgetManager.GetAllWidgetsBySetID(self.widgetSetID);
  407. for _, widgetInfo in ipairs(setWidgets) do
  408. self:ProcessWidget(widgetInfo.widgetID, widgetInfo.widgetType);
  409. end
  410. -- Animate out any widgets that are still marked for removal
  411. self:AnimateOutAllMarkedWidgets();
  412. -- Force call UpdateWidgetLayout because some containers rely on it being called right away
  413. self:UpdateWidgetLayout();
  414. end
  415. local function SortWidgets(a, b)
  416. if a.orderIndex == b.orderIndex then
  417. return a.widgetID < b.widgetID;
  418. else
  419. return a.orderIndex < b.orderIndex;
  420. end
  421. end
  422. function UIWidgetContainerMixin:GetNumWidgetsShowing()
  423. return self.numWidgetsShowing or 0;
  424. end
  425. function UIWidgetContainerMixin:HasAnyWidgetsShowing()
  426. return (self:GetNumWidgetsShowing() > 0);
  427. end
  428. function UIWidgetContainerMixin:UpdateWidgetLayout()
  429. local sortedWidgets = {};
  430. for _, widget in pairs(self.widgetFrames) do
  431. table.insert(sortedWidgets, widget);
  432. end
  433. table.sort(sortedWidgets, SortWidgets);
  434. self.numWidgetsShowing = #sortedWidgets;
  435. self:layoutFunc(sortedWidgets);
  436. self.dirtyLayout = false;
  437. end
  438. UIWidgetManagerMixin = {};
  439. function UIWidgetManagerMixin:OnLoad()
  440. self.widgetVisTypeInfo = {};
  441. self.registeredWidgetContainers = {};
  442. end
  443. function UIWidgetManagerMixin:OnWidgetContainerRegistered(widgetContainer)
  444. self.registeredWidgetContainers[widgetContainer] = true;
  445. end
  446. function UIWidgetManagerMixin:OnWidgetContainerUnregistered(widgetContainer)
  447. self.registeredWidgetContainers[widgetContainer] = nil;
  448. end
  449. function UIWidgetManagerMixin:UpdateProcessingUnit(attachedUnit, attachedUnitIsGuid)
  450. if self.processingUnit ~= attachedUnit then
  451. if attachedUnitIsGuid then
  452. C_UIWidgetManager.SetProcessingUnitGuid(attachedUnit);
  453. else
  454. C_UIWidgetManager.SetProcessingUnit(attachedUnit);
  455. end
  456. self.processingUnit = attachedUnit;
  457. end
  458. end
  459. function UIWidgetManagerMixin:GetWidgetTypeInfo(widgetType)
  460. return self.widgetVisTypeInfo[widgetType];
  461. end
  462. -- templateInfo should be a table that contains 2 entries (frameType and frameTemplate)
  463. -- visInfoDataFunction should be a function that gets the widget visInfo object. It should return this visInfo object. If something in the data indicates the widget should not show it should return nil.
  464. function UIWidgetManagerMixin:RegisterWidgetVisTypeTemplate(visType, templateInfo, visInfoDataFunction)
  465. if not visType or not templateInfo or not templateInfo.frameType or not templateInfo.frameTemplate or not visInfoDataFunction then
  466. -- All these things are required
  467. return;
  468. end
  469. if self.widgetVisTypeInfo[visType] then
  470. -- Someone already registered for this visType, so do nothing
  471. return;
  472. end
  473. self.widgetVisTypeInfo[visType] = { templateInfo = templateInfo, visInfoDataFunction = visInfoDataFunction };
  474. end
  475. -- This function will return an enumerator for all currently-visible widgets that are flagged with the passed widgetTag.
  476. -- Example use:
  477. -- for index, widgetFrame in UIWidgetManager:EnumerateWidgetsByWidgetTag("myTag") do
  478. -- -- YOUR CODE
  479. -- end
  480. function UIWidgetManagerMixin:EnumerateWidgetsByWidgetTag(widgetTag)
  481. local widgetFrames = {};
  482. for widgetContainer in pairs(self.registeredWidgetContainers) do
  483. widgetContainer:GatherWidgetsByWidgetTag(widgetFrames, widgetTag);
  484. end
  485. return pairs(widgetFrames);
  486. end