List of commits:
Subject Hash Author Date (UTC)
feat(choir): Unit button contextual menu 981e9016b0c9a377219a13d2716d09de899efe60 Vladyslav Bondarenko 2022-01-08 10:06:50
fix(choir): Update range indicator correctly e2810d30fe62427920479057e1cc28f3ed45ff31 Vladyslav Bondarenko 2022-01-08 03:34:08
fix(choir): Raid frame and spoiler overlap e1a8da43270859a3c36b67f81357a935f0b6f2ef Vladyslav Bondarenko 2022-01-08 02:00:26
fix(choir): Update only existing units when necessary 82b7e0cfd4354263f27ea206f555e9771f2e8f8c Vladyslav Bondarenko 2021-12-31 07:45:00
feat(choir): Render unit threat situation dee7167e3a7e453425248a1062560f9bfd8b3bb4 Vladyslav Bondarenko 2021-12-28 01:39:09
fix(choir): Render dungeon role correctly for Cata 590a4abfd82659624688c4c1658de87693d3cd30 Vladyslav Bondarenko 2021-12-28 00:31:52
fix(choir): Show raid frame at player login 21a86d3840fb810c4ff4c67490aae7d5251c1bae Vladyslav Bondarenko 2021-11-24 06:07:10
feat(choir)!: Add interface options for raid frame ce677d3d0e7cfe05d1da5b159f52a0808db9ce9a Vladyslav Bondarenko 2021-11-24 06:05:37
feat(choir): Add conf spell shortcut default button c8e2c3493896f5ae589c516f742bbafd528140db Vladyslav Bondarenko 2021-11-24 02:28:19
feat(choir)!: Add configuration menu 12319ce873aecea4bfc0addec7c5ac5c1f225237 Vladyslav Bondarenko 2021-11-21 09:26:05
feat(choir): Add unit game tooltip 3ec490e489bb105f5096d5bb3e56814873deec3f Vladyslav Bondarenko 2021-11-20 09:34:12
fix(choir): Raid group frame arrange correctly b592f3f018ee521a821447ccf837aded703ad447 Vladyslav Bondarenko 2021-11-18 22:02:52
feat(choir): Render group role indicator for units 5f3a7c24d3f79035b8faa156355a2d017688134e Vladyslav Bondarenko 2021-11-18 22:02:27
feat(choir): Adjust raid group frame position f99a54133a1761034baca93bfa8814c614191818 Vladyslav Bondarenko 2021-11-18 00:35:35
feat(choir): Add debuff buttons for raid fe66339420a9eb5e4823cc4fe45e0d97b2983073 Vladyslav Bondarenko 2021-11-17 00:55:54
feat(choir): Add texture to health bars ddaeb29d7ecfd95a98bcc85b3f4f7676c7ccd4d7 Vladyslav Bondarenko 2021-11-14 21:40:26
fix(choir)!: Obscure critical error 0f203b4d69f57240e97c66f1ab4510c6ac3e9276 Vladyslav Bondarenko 2021-11-11 12:52:02
feat(choir): Toggle button visibility given roster d193e7b5eb38cb3ac69d74eec1f96e00d90b6098 Vladyslav Bondarenko 2021-11-10 23:46:24
feat(choir)!: Add permanent raid frame 1839c35af4212c09038e972547d6b5893a9ce219 Vladyslav Bondarenko 2021-11-10 16:04:25
feat(choir)!: Employ Clearcasting subset feat 733c81538c3c965f07993fd7ddc482e724121b75 Vladyslav Bondarenko 2021-11-04 22:40:48
Commit 981e9016b0c9a377219a13d2716d09de899efe60 - feat(choir): Unit button contextual menu
When user right-clicks on a Choir raid unit button, render a contextual
menu, similar to the native contextual menu that appears on the native
unit buttons.

This is mostly for convenience and to provide expected functionality.

Make unit selection spoiler toggle only on left click. Otherwise the
context menu does not work correctly for spoiler unit buttons.
Author: Vladyslav Bondarenko
Author date (UTC): 2022-01-08 10:06
Committer name: Vladyslav Bondarenko
Committer date (UTC): 2022-01-08 10:06
Parent(s): ce396a314ffa2beb0a23787dcad5a8d1549d50e8
Signer:
Signing key:
Signing status: N
Tree: 9c345ad3f36aa70915f8ce49f026d106046c4d8b
File Lines added Lines deleted
.luacheckrc 14 0
choir.lua 104 7
File .luacheckrc changed (mode: 100644) (index cc885a2..ce107b5)
... ... stds.wow = {
18 18 'IsSpellInRange', 'IsSpellInRange',
19 19 'NumberFont_OutlineThick_Mono_Small', 'NumberFont_OutlineThick_Mono_Small',
20 20 'RAID_CLASS_COLORS', 'RAID_CLASS_COLORS',
21 'RAID_TARGET_ICON',
21 22 'RegisterUnitWatch', 'RegisterUnitWatch',
22 23 'ReloadUI', 'ReloadUI',
24 'SecureUnitButton_OnLoad',
23 25 'SetOverrideBinding', 'SetOverrideBinding',
26 'ToggleDropDownMenu',
27 'UIDropDownMenu_Initialize',
24 28 'UIParent', 'UIParent',
29 'UnitCanAttack',
30 'UnitCanCooperate',
25 31 'UnitClass', 'UnitClass',
26 32 'UnitExists', 'UnitExists',
27 33 'UnitExists', 'UnitExists',
28 34 'UnitGroupRolesAssigned', 'UnitGroupRolesAssigned',
29 35 'UnitHealth', 'UnitHealth',
30 36 'UnitHealthMax', 'UnitHealthMax',
37 'UnitInParty',
38 'UnitInRaid',
31 39 'UnitIsDead', 'UnitIsDead',
32 40 'UnitIsGhost', 'UnitIsGhost',
41 'UnitIsMercenary',
42 'UnitIsPlayer',
43 'UnitIsUnit',
33 44 'UnitName', 'UnitName',
34 45 'UnitPlayerOrPetInRaid', 'UnitPlayerOrPetInRaid',
46 'UnitPopupMenus',
47 'UnitPopup_ShowMenu',
35 48 'UnitThreatSituation', 'UnitThreatSituation',
36 49 'UnregisterUnitWatch', 'UnregisterUnitWatch',
37 50 'date', 'date',
 
... ... stds.choir = {
45 58 'ChoirConfRaidFlag', 'ChoirConfRaidFlag',
46 59 'ChoirConfRaidX', 'ChoirConfRaidX',
47 60 'ChoirConfRaidY', 'ChoirConfRaidY',
61 'ChoirContextualMenu',
48 62 'ChoirRangeSpellName', 'ChoirRangeSpellName',
49 63 'ChoirShortcutBindingKeyMap', 'ChoirShortcutBindingKeyMap',
50 64 'ChoirShortcutSpellNameList', 'ChoirShortcutSpellNameList',
File choir.lua changed (mode: 100644) (index 148f441..4a4413b)
... ... local function healthBarUpdateProcessor(self, elapsedDurationSec)
300 300 self.idleDurationSec = idleDurationSec - elapsedDurationSec self.idleDurationSec = idleDurationSec - elapsedDurationSec
301 301 else else
302 302 self.idleDurationSec = math.abs(updateFrequencyPerSecond) self.idleDurationSec = math.abs(updateFrequencyPerSecond)
303
303 304 healthBarUpdateOverlay(self, self.overlay, self:GetAttribute('unit')) healthBarUpdateOverlay(self, self.overlay, self:GetAttribute('unit'))
304 305 end end
305 306 end end
 
... ... local function createClearcastingSubset(unitButton, targetFilter)
577 578 columnQuantity, rowQuantity) columnQuantity, rowQuantity)
578 579 end end
579 580
581 --[[--
582 Populate given menuFrame with menu buttons.
583
584 The menu buttons that will be added to the given contextual menu
585 are those that were defined by the baseline game client
586 for the TargetFrameDropDown, PlayerFrameDropDown and others,
587 declared in UnitPopupFrames global variable that is a table.
588
589 There is an important implicit parameter menuFrame.unit.
590 The property is set in contextualMenuOnShowCallback.
591
592 It is done this way to avoid creating redundant menu frames
593 for every unit button. Instead, this approach reuses the singleton
594 menu frame for every of 9*5 menu buttons that the add-on creates.
595
596 @function contenxtualMenuOnClickCallback
597 @arg menuFrame given menu frame, likely ChoirContextualMenu
598 ]]
599 local function contextualMenuOnClickCallback(menuFrame)
600 assert (menuFrame ~= nil)
601 --[[ See https://github.com/Ennie/wow-ui-source/blob/master/FrameXML/UnitPopup.lua ]]--
602 --[[ See https://www.townlong-yak.com/framexml/live/TargetFrame.lua ]]--
603 local unitDesignation = menuFrame.unit or 'target'
604 local menuCategory
605 local name, id
606 if UnitIsUnit(unitDesignation, "player") then
607 menuCategory = "SELF"
608 elseif UnitIsUnit(unitDesignation, "vehicle") then
609 menuCategory = "VEHICLE"
610 elseif UnitIsUnit(unitDesignation, "pet") then
611 menuCategory = "PET"
612 elseif UnitIsPlayer(unitDesignation) then
613 id = UnitInRaid(unitDesignation)
614 if id then
615 menuCategory = "RAID_PLAYER"
616 elseif UnitInParty(unitDesignation) then
617 menuCategory = "PARTY"
618 else
619 if not UnitIsMercenary("player") then
620 if UnitCanCooperate("player", unitDesignation) then
621 menuCategory = "PLAYER";
622 else
623 menuCategory = "ENEMY_PLAYER"
624 end
625 else
626 if UnitCanAttack("player", unitDesignation) then
627 menuCategory = "ENEMY_PLAYER"
628 else
629 menuCategory = "PLAYER";
630 end
631 end
632 end
633 else
634 menuCategory = "TARGET"
635 name = RAID_TARGET_ICON
636 end
637 assert (UnitPopupMenus[menuCategory] ~= nil)
638 UnitPopup_ShowMenu(menuFrame, menuCategory, unitDesignation, name, id)
639 end
640
641 local function createContextualMenu()
642 --[[ See https://wowwiki-archive.fandom.com/wiki/UI_Object_UIDropDownMenu ]]--
643 local menuFrame = CreateFrame('FRAME', 'ChoirContextualMenu', ChoirFrame, 'UIDropDownMenuTemplate')
644 assert (menuFrame ~= nil)
645 UIDropDownMenu_Initialize(menuFrame, contextualMenuOnClickCallback, 'MENU')
646
647 return menuFrame
648 end
649
650 local function contextualMenuOnShowCallback(targetFrame, unitDesignation, mouseButtonDesignation)
651 assert (targetFrame ~= nil)
652 assert (unitDesignation ~= nil)
653 if mouseButtonDesignation ~= 'RightButton' then
654 return
655 end
656 local menuFrame = ChoirContextualMenu
657 assert (menuFrame ~= nil)
658 menuFrame.unit = unitDesignation
659 ToggleDropDownMenu(1, nil, menuFrame, targetFrame:GetName(), 144, 12)
660 end
661
580 662 local function createUnitButton(parentFrame, frameName, unit, local function createUnitButton(parentFrame, frameName, unit,
581 663 someFilterDescriptorFirst, someFilterDescriptorLast, width, height) someFilterDescriptorFirst, someFilterDescriptorLast, width, height)
582 664 assert (parentFrame ~= nil) assert (parentFrame ~= nil)
 
... ... local function createUnitButton(parentFrame, frameName, unit,
588 670 createBindingKeyHandler(u) createBindingKeyHandler(u)
589 671 createInheritanceHandler(u) createInheritanceHandler(u)
590 672
591 u:SetAttribute('type', 'target')
673 u:SetAttribute('type1', 'target')
592 674
593 675 local padding = 4 local padding = 4
594 676 if not width then if not width then
 
... ... local function createUnitButton(parentFrame, frameName, unit,
608 690
609 691 u:SetAttribute('unit', unit) u:SetAttribute('unit', unit)
610 692
693 u:RegisterForClicks('AnyUp')
694 u:SetAttribute('*type2', 'menu')
695 SecureUnitButton_OnLoad(u, unit, contextualMenuOnShowCallback);
696
611 697 local roleWidget = createRoleWidget(u) local roleWidget = createRoleWidget(u)
612 698 local headerFrame = createHeader(u, width, 24) local headerFrame = createHeader(u, width, 24)
613 699 local healthBarFrame = createHealthBar(u, width, 24) local healthBarFrame = createHealthBar(u, width, 24)
 
... ... local function createGroup(rootFrame, groupNumber, unitTable)
882 968 --[[ Assume that parent is the spoiler frame --[[ Assume that parent is the spoiler frame
883 969 -- which was created with createSpoiler and -- which was created with createSpoiler and
884 970 -- has required scripts hooked to it ]]-- -- has required scripts hooked to it ]]--
885 local spoilerFrame = self:GetParent()
886 spoilerFrame:Hide()
971 if 'LeftButton' == button then
972 local spoilerFrame = self:GetParent()
973 spoilerFrame:Hide()
974 end
887 975 ]=]) ]=])
888 976 b:Hide() b:Hide()
889 977
 
... ... local function initRangeSpellName(rootFrame)
1282 1370 return s return s
1283 1371 end end
1284 1372
1285 local function initSpoiler(rootFrame)
1373 local function initSpoiler(rootFrame, contextualMenu)
1286 1374 assert (rootFrame ~= nil) assert (rootFrame ~= nil)
1375 --[[ NOTE Unit buttons require unit contextual menu to be initialized ]]--
1376 assert (contextualMenu ~= nil)
1287 1377
1288 1378 --[[ WARNING All mutually exclusive frames must be placed under the same parent, --[[ WARNING All mutually exclusive frames must be placed under the same parent,
1289 1379 -- for the spoiler toggling to work correctly. -- for the spoiler toggling to work correctly.
 
... ... local function initSpoiler(rootFrame)
1316 1406 return spoilerHolder return spoilerHolder
1317 1407 end end
1318 1408
1319 local function initRaidFrame(rootFrame, spoilerHolder)
1409 local function initRaidFrame(rootFrame, spoilerHolder, contextualMenu)
1410 --[[ NOTE Unit buttons require unit contextual menu to be initialized ]]--
1411 assert (contextualMenu ~= nil)
1320 1412 return createRaidFrame(rootFrame, spoilerHolder) return createRaidFrame(rootFrame, spoilerHolder)
1321 1413 end end
1322 1414
 
... ... local function initConf(rootFrame, raidFrame)
1771 1863 return confFrame, bindingKeyFrame return confFrame, bindingKeyFrame
1772 1864 end end
1773 1865
1866 local function initContextualMenu()
1867 return createContextualMenu()
1868 end
1869
1774 1870 local function init(rootFrame) local function init(rootFrame)
1775 1871 assert (rootFrame ~= nil) assert (rootFrame ~= nil)
1776 1872
 
... ... local function init(rootFrame)
1782 1878 rootFrame:SetAllPoints() rootFrame:SetAllPoints()
1783 1879
1784 1880 initRangeSpellName(rootFrame) initRangeSpellName(rootFrame)
1785 local spoilerHolder = initSpoiler(rootFrame)
1786 local raidFrame = initRaidFrame(rootFrame, spoilerHolder)
1881 local contextualMenu = initContextualMenu()
1882 local spoilerHolder = initSpoiler(rootFrame, contextualMenu)
1883 local raidFrame = initRaidFrame(rootFrame, spoilerHolder, contextualMenu)
1787 1884 initConf(rootFrame, raidFrame) initConf(rootFrame, raidFrame)
1788 1885
1789 1886 trace('init') trace('init')
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/vrtc/choir

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/vrtc/choir

Clone this repository using git:
git clone git://git.rocketgit.com/user/vrtc/choir

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main