UiRadioButtonGroupComponent.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "UiRadioButtonGroupComponent.h"
  9. #include <AzCore/Serialization/SerializeContext.h>
  10. #include <AzCore/Serialization/EditContext.h>
  11. #include <AzCore/RTTI/BehaviorContext.h>
  12. #include <LyShine/Bus/UiCanvasBus.h>
  13. #include <LyShine/Bus/UiElementBus.h>
  14. #include <LyShine/Bus/UiRadioButtonBus.h>
  15. #include <LyShine/Bus/UiRadioButtonCommunicationBus.h>
  16. #include <LyShine/UiSerializeHelpers.h>
  17. #include "UiSerialize.h"
  18. ////////////////////////////////////////////////////////////////////////////////////////////////////
  19. //! UiRadioButtonGroupNotificationBus Behavior context handler class
  20. class UiRadioButtonGroupNotificationBusBehaviorHandler
  21. : public UiRadioButtonGroupNotificationBus::Handler
  22. , public AZ::BehaviorEBusHandler
  23. {
  24. public:
  25. AZ_EBUS_BEHAVIOR_BINDER(UiRadioButtonGroupNotificationBusBehaviorHandler, "{A8D1A53C-7419-4EBA-8B73-EA4C5F6ED2DA}", AZ::SystemAllocator,
  26. OnRadioButtonGroupStateChange);
  27. void OnRadioButtonGroupStateChange(AZ::EntityId checked) override
  28. {
  29. Call(FN_OnRadioButtonGroupStateChange, checked);
  30. }
  31. };
  32. ////////////////////////////////////////////////////////////////////////////////////////////////////
  33. // PUBLIC MEMBER FUNCTIONS
  34. ////////////////////////////////////////////////////////////////////////////////////////////////////
  35. ////////////////////////////////////////////////////////////////////////////////////////////////////
  36. UiRadioButtonGroupComponent::UiRadioButtonGroupComponent()
  37. : m_allowUncheck(false)
  38. {
  39. }
  40. ////////////////////////////////////////////////////////////////////////////////////////////////////
  41. UiRadioButtonGroupComponent::~UiRadioButtonGroupComponent()
  42. {
  43. }
  44. ////////////////////////////////////////////////////////////////////////////////////////////////////
  45. AZ::EntityId UiRadioButtonGroupComponent::GetCheckedRadioButton()
  46. {
  47. return m_checkedEntity;
  48. }
  49. ////////////////////////////////////////////////////////////////////////////////////////////////////
  50. void UiRadioButtonGroupComponent::SetState(AZ::EntityId radioButton, bool isOn)
  51. {
  52. SetStateCommon(radioButton, isOn, false);
  53. }
  54. ////////////////////////////////////////////////////////////////////////////////////////////////////
  55. bool UiRadioButtonGroupComponent::GetAllowUncheck()
  56. {
  57. return m_allowUncheck;
  58. }
  59. ////////////////////////////////////////////////////////////////////////////////////////////////////
  60. void UiRadioButtonGroupComponent::SetAllowUncheck(bool allowUncheck)
  61. {
  62. m_allowUncheck = allowUncheck;
  63. }
  64. ////////////////////////////////////////////////////////////////////////////////////////////////////
  65. void UiRadioButtonGroupComponent::AddRadioButton(AZ::EntityId radioButton)
  66. {
  67. if (RegisterRadioButton(radioButton))
  68. {
  69. // Let it know it is now in the group
  70. UiRadioButtonCommunicationBus::Event(radioButton, &UiRadioButtonCommunicationBus::Events::SetGroup, GetEntityId());
  71. }
  72. }
  73. ////////////////////////////////////////////////////////////////////////////////////////////////////
  74. void UiRadioButtonGroupComponent::RemoveRadioButton(AZ::EntityId radioButton)
  75. {
  76. UiRadioButtonCommunicationBus::Event(radioButton, &UiRadioButtonCommunicationBus::Events::SetGroup, AZ::EntityId());
  77. UnregisterRadioButton(radioButton);
  78. }
  79. ////////////////////////////////////////////////////////////////////////////////////////////////////
  80. bool UiRadioButtonGroupComponent::ContainsRadioButton(AZ::EntityId radioButton)
  81. {
  82. return m_radioButtons.find(radioButton) != m_radioButtons.end();
  83. }
  84. ////////////////////////////////////////////////////////////////////////////////////////////////////
  85. const LyShine::ActionName& UiRadioButtonGroupComponent::GetChangedActionName()
  86. {
  87. return m_changedActionName;
  88. }
  89. ////////////////////////////////////////////////////////////////////////////////////////////////////
  90. void UiRadioButtonGroupComponent::SetChangedActionName(const LyShine::ActionName& actionName)
  91. {
  92. m_changedActionName = actionName;
  93. }
  94. ////////////////////////////////////////////////////////////////////////////////////////////////////
  95. bool UiRadioButtonGroupComponent::RegisterRadioButton(AZ::EntityId radioButton)
  96. {
  97. // Check if the given entity actually has the radio button component on it
  98. bool isRadioButton = UiRadioButtonBus::FindFirstHandler(radioButton) != nullptr;
  99. // Check that the button is actually a radio button before adding it to the group
  100. if (isRadioButton)
  101. {
  102. // Try adding the button to the group, and if it wasn't in the group before then
  103. if (m_radioButtons.insert(radioButton).second)
  104. {
  105. // If the button that is getting added is already checked, uncheck the currently checked one
  106. bool isOn;
  107. UiRadioButtonBus::EventResult(isOn, radioButton, &UiRadioButtonBus::Events::GetState);
  108. if (isOn)
  109. {
  110. if (m_checkedEntity.IsValid())
  111. {
  112. // Uncheck our currently checked entity
  113. UiRadioButtonCommunicationBus::Event(m_checkedEntity, &UiRadioButtonCommunicationBus::Events::SetState, false, false);
  114. m_checkedEntity.SetInvalid();
  115. }
  116. m_checkedEntity = radioButton;
  117. }
  118. return true;
  119. }
  120. }
  121. return false;
  122. }
  123. ////////////////////////////////////////////////////////////////////////////////////////////////////
  124. void UiRadioButtonGroupComponent::UnregisterRadioButton(AZ::EntityId radioButton)
  125. {
  126. m_radioButtons.erase(radioButton);
  127. // If the button that is getting removed was the checked entity, set the check entity to invalid
  128. if (radioButton == m_checkedEntity)
  129. {
  130. m_checkedEntity.SetInvalid();
  131. }
  132. }
  133. ////////////////////////////////////////////////////////////////////////////////////////////////////
  134. void UiRadioButtonGroupComponent::RequestRadioButtonStateChange(AZ::EntityId radioButton, bool newState)
  135. {
  136. SetStateCommon(radioButton, newState, true);
  137. }
  138. ////////////////////////////////////////////////////////////////////////////////////////////////////
  139. // PROTECTED MEMBER FUNCTIONS
  140. ////////////////////////////////////////////////////////////////////////////////////////////////////
  141. ////////////////////////////////////////////////////////////////////////////////////////////////////
  142. void UiRadioButtonGroupComponent::Activate()
  143. {
  144. UiRadioButtonGroupBus::Handler::BusConnect(GetEntityId());
  145. UiRadioButtonGroupCommunicationBus::Handler::BusConnect(GetEntityId());
  146. }
  147. ////////////////////////////////////////////////////////////////////////////////////////////////////
  148. void UiRadioButtonGroupComponent::Deactivate()
  149. {
  150. UiRadioButtonGroupBus::Handler::BusDisconnect(GetEntityId());
  151. UiRadioButtonGroupCommunicationBus::Handler::BusDisconnect(GetEntityId());
  152. }
  153. ////////////////////////////////////////////////////////////////////////////////////////////////////
  154. // PROTECTED STATIC MEMBER FUNCTIONS
  155. ////////////////////////////////////////////////////////////////////////////////////////////////////
  156. void UiRadioButtonGroupComponent::Reflect(AZ::ReflectContext* context)
  157. {
  158. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  159. if (serializeContext)
  160. {
  161. serializeContext->Class<UiRadioButtonGroupComponent, AZ::Component>()
  162. ->Version(1)
  163. // Settings group
  164. ->Field("AllowRestoreUnchecked", &UiRadioButtonGroupComponent::m_allowUncheck)
  165. // Actions group
  166. ->Field("ChangedActionName", &UiRadioButtonGroupComponent::m_changedActionName);
  167. AZ::EditContext* ec = serializeContext->GetEditContext();
  168. if (ec)
  169. {
  170. auto editInfo = ec->Class<UiRadioButtonGroupComponent>("RadioButtonGroup", "A component for RadioButtonGroup behavior.");
  171. editInfo->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  172. ->Attribute(AZ::Edit::Attributes::Category, "UI")
  173. ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/UiRadioButtonGroup.png")
  174. ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/UiRadioButtonGroup.png")
  175. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("UI", 0x27ff46b0))
  176. ->Attribute(AZ::Edit::Attributes::AutoExpand, true);
  177. // Settings group
  178. {
  179. editInfo->ClassElement(AZ::Edit::ClassElements::Group, "Settings")
  180. ->Attribute(AZ::Edit::Attributes::AutoExpand, true);
  181. editInfo->DataElement(0, &UiRadioButtonGroupComponent::m_allowUncheck, "Allow uncheck", "Allow clicking on the selected radio button to uncheck it.");
  182. }
  183. // Actions group
  184. {
  185. editInfo->ClassElement(AZ::Edit::ClassElements::Group, "Actions")
  186. ->Attribute(AZ::Edit::Attributes::AutoExpand, true);
  187. editInfo->DataElement(0, &UiRadioButtonGroupComponent::m_changedActionName, "Change", "The action triggered when value changes.");
  188. }
  189. }
  190. }
  191. AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
  192. if (behaviorContext)
  193. {
  194. behaviorContext->EBus<UiRadioButtonGroupBus>("UiRadioButtonGroupBus")
  195. ->Event("GetState", &UiRadioButtonGroupBus::Events::GetCheckedRadioButton)
  196. ->Event("SetState", &UiRadioButtonGroupBus::Events::SetState)
  197. ->Event("GetAllowUncheck", &UiRadioButtonGroupBus::Events::GetAllowUncheck)
  198. ->Event("SetAllowUncheck", &UiRadioButtonGroupBus::Events::SetAllowUncheck)
  199. ->Event("AddRadioButton", &UiRadioButtonGroupBus::Events::AddRadioButton)
  200. ->Event("RemoveRadioButton", &UiRadioButtonGroupBus::Events::RemoveRadioButton)
  201. ->Event("ContainsRadioButton", &UiRadioButtonGroupBus::Events::ContainsRadioButton)
  202. ->Event("GetChangedActionName", &UiRadioButtonGroupBus::Events::GetChangedActionName)
  203. ->Event("SetChangedActionName", &UiRadioButtonGroupBus::Events::SetChangedActionName);
  204. behaviorContext->EBus<UiRadioButtonGroupNotificationBus>("UiRadioButtonGroupNotificationBus")
  205. ->Handler<UiRadioButtonGroupNotificationBusBehaviorHandler>();
  206. }
  207. }
  208. ////////////////////////////////////////////////////////////////////////////////////////////////////
  209. void UiRadioButtonGroupComponent::SetStateCommon(AZ::EntityId radioButton, bool isOn, bool sendNotifications)
  210. {
  211. // First check if the button is actually in the group
  212. if (radioButton.IsValid() && ContainsRadioButton(radioButton))
  213. {
  214. // If this is a request to be checked
  215. if (isOn)
  216. {
  217. // Check if we currently have a checked radio button
  218. if (m_checkedEntity.IsValid())
  219. {
  220. UiRadioButtonCommunicationBus::Event(
  221. m_checkedEntity, &UiRadioButtonCommunicationBus::Events::SetState, false, sendNotifications);
  222. m_checkedEntity.SetInvalid();
  223. }
  224. m_checkedEntity = radioButton;
  225. UiRadioButtonCommunicationBus::Event(
  226. m_checkedEntity, &UiRadioButtonCommunicationBus::Events::SetState, true, sendNotifications);
  227. }
  228. else if (m_allowUncheck && radioButton == m_checkedEntity) // && isOn == false
  229. {
  230. UiRadioButtonCommunicationBus::Event(
  231. m_checkedEntity, &UiRadioButtonCommunicationBus::Events::SetState, false, sendNotifications);
  232. m_checkedEntity.SetInvalid();
  233. }
  234. else // we didn't change anything, don't send events
  235. {
  236. return;
  237. }
  238. if (sendNotifications)
  239. {
  240. if (!m_changedActionName.empty())
  241. {
  242. AZ::EntityId canvasEntityId;
  243. UiElementBus::EventResult(canvasEntityId, GetEntityId(), &UiElementBus::Events::GetCanvasEntityId);
  244. UiCanvasNotificationBus::Event(canvasEntityId, &UiCanvasNotificationBus::Events::OnAction, GetEntityId(), m_changedActionName);
  245. }
  246. UiRadioButtonGroupNotificationBus::Event(
  247. GetEntityId(), &UiRadioButtonGroupNotificationBus::Events::OnRadioButtonGroupStateChange, m_checkedEntity);
  248. }
  249. }
  250. }