The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
7.8KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wlanguage-extension-token")
  21. //==============================================================================
  22. class UIASelectionItemProvider : public UIAProviderBase,
  23. public ComBaseClassHelper<ComTypes::ISelectionItemProvider>
  24. {
  25. public:
  26. explicit UIASelectionItemProvider (AccessibilityNativeHandle* handle)
  27. : UIAProviderBase (handle),
  28. isRadioButton (getHandler().getRole() == AccessibilityRole::radioButton)
  29. {
  30. }
  31. //==============================================================================
  32. JUCE_COMRESULT AddToSelection() override
  33. {
  34. if (! isElementValid())
  35. return (HRESULT) UIA_E_ELEMENTNOTAVAILABLE;
  36. const auto& handler = getHandler();
  37. if (isRadioButton)
  38. {
  39. handler.getActions().invoke (AccessibilityActionType::press);
  40. sendAccessibilityAutomationEvent (handler, ComTypes::UIA_SelectionItem_ElementSelectedEventId);
  41. return S_OK;
  42. }
  43. handler.getActions().invoke (AccessibilityActionType::toggle);
  44. handler.getActions().invoke (AccessibilityActionType::press);
  45. return S_OK;
  46. }
  47. JUCE_COMRESULT get_IsSelected (BOOL* pRetVal) override
  48. {
  49. return withCheckedComArgs (pRetVal, *this, [&]
  50. {
  51. const auto state = getHandler().getCurrentState();
  52. *pRetVal = isRadioButton ? state.isChecked() : state.isSelected();
  53. return S_OK;
  54. });
  55. }
  56. JUCE_COMRESULT get_SelectionContainer (IRawElementProviderSimple** pRetVal) override
  57. {
  58. return withCheckedComArgs (pRetVal, *this, [&]
  59. {
  60. if (! isRadioButton)
  61. if (auto* parent = getHandler().getParent())
  62. parent->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  63. return S_OK;
  64. });
  65. }
  66. JUCE_COMRESULT RemoveFromSelection() override
  67. {
  68. if (! isElementValid())
  69. return (HRESULT) UIA_E_ELEMENTNOTAVAILABLE;
  70. if (! isRadioButton)
  71. {
  72. const auto& handler = getHandler();
  73. if (handler.getCurrentState().isSelected())
  74. getHandler().getActions().invoke (AccessibilityActionType::toggle);
  75. }
  76. return S_OK;
  77. }
  78. JUCE_COMRESULT Select() override
  79. {
  80. if (! isElementValid())
  81. return (HRESULT) UIA_E_ELEMENTNOTAVAILABLE;
  82. AddToSelection();
  83. if (isElementValid() && ! isRadioButton)
  84. {
  85. const auto& handler = getHandler();
  86. if (auto* parent = handler.getParent())
  87. for (auto* child : parent->getChildren())
  88. if (child != &handler && child->getCurrentState().isSelected())
  89. child->getActions().invoke (AccessibilityActionType::toggle);
  90. }
  91. return S_OK;
  92. }
  93. private:
  94. const bool isRadioButton;
  95. //==============================================================================
  96. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIASelectionItemProvider)
  97. };
  98. //==============================================================================
  99. class UIASelectionProvider : public UIAProviderBase,
  100. public ComBaseClassHelper<ComTypes::ISelectionProvider2>
  101. {
  102. public:
  103. using UIAProviderBase::UIAProviderBase;
  104. //==============================================================================
  105. JUCE_COMRESULT QueryInterface (REFIID iid, void** result) override
  106. {
  107. if (iid == __uuidof (IUnknown) || iid == __uuidof (ComTypes::ISelectionProvider))
  108. return castToType<ComTypes::ISelectionProvider> (result);
  109. if (iid == __uuidof (ComTypes::ISelectionProvider2))
  110. return castToType<ComTypes::ISelectionProvider2> (result);
  111. *result = nullptr;
  112. return E_NOINTERFACE;
  113. }
  114. //==============================================================================
  115. JUCE_COMRESULT get_CanSelectMultiple (BOOL* pRetVal) override
  116. {
  117. return withCheckedComArgs (pRetVal, *this, [&]
  118. {
  119. *pRetVal = isMultiSelectable();
  120. return S_OK;
  121. });
  122. }
  123. JUCE_COMRESULT get_IsSelectionRequired (BOOL* pRetVal) override
  124. {
  125. return withCheckedComArgs (pRetVal, *this, [&]
  126. {
  127. *pRetVal = getSelectedChildren().size() > 0 && ! isMultiSelectable();
  128. return S_OK;
  129. });
  130. }
  131. JUCE_COMRESULT GetSelection (SAFEARRAY** pRetVal) override
  132. {
  133. return withCheckedComArgs (pRetVal, *this, [&]
  134. {
  135. return addHandlersToArray (getSelectedChildren(), pRetVal);
  136. });
  137. }
  138. //==============================================================================
  139. JUCE_COMRESULT get_FirstSelectedItem (IRawElementProviderSimple** pRetVal) override
  140. {
  141. return withCheckedComArgs (pRetVal, *this, [&]
  142. {
  143. auto selectedChildren = getSelectedChildren();
  144. if (! selectedChildren.empty())
  145. selectedChildren.front()->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  146. return S_OK;
  147. });
  148. }
  149. JUCE_COMRESULT get_LastSelectedItem (IRawElementProviderSimple** pRetVal) override
  150. {
  151. return withCheckedComArgs (pRetVal, *this, [&]
  152. {
  153. auto selectedChildren = getSelectedChildren();
  154. if (! selectedChildren.empty())
  155. selectedChildren.back()->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  156. return S_OK;
  157. });
  158. }
  159. JUCE_COMRESULT get_CurrentSelectedItem (IRawElementProviderSimple** pRetVal) override
  160. {
  161. return withCheckedComArgs (pRetVal, *this, [&]
  162. {
  163. get_FirstSelectedItem (pRetVal);
  164. return S_OK;
  165. });
  166. }
  167. JUCE_COMRESULT get_ItemCount (int* pRetVal) override
  168. {
  169. return withCheckedComArgs (pRetVal, *this, [&]
  170. {
  171. *pRetVal = (int) getSelectedChildren().size();
  172. return S_OK;
  173. });
  174. }
  175. private:
  176. bool isMultiSelectable() const noexcept
  177. {
  178. return getHandler().getCurrentState().isMultiSelectable();
  179. }
  180. std::vector<const AccessibilityHandler*> getSelectedChildren() const
  181. {
  182. std::vector<const AccessibilityHandler*> selectedHandlers;
  183. for (auto* child : getHandler().getComponent().getChildren())
  184. if (auto* handler = child->getAccessibilityHandler())
  185. if (handler->getCurrentState().isSelected())
  186. selectedHandlers.push_back (handler);
  187. return selectedHandlers;
  188. }
  189. //==============================================================================
  190. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIASelectionProvider)
  191. };
  192. JUCE_END_IGNORE_WARNINGS_GCC_LIKE
  193. } // namespace juce