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.

248 lines
7.9KB

  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. using namespace ComTypes::Constants;
  40. handler.getActions().invoke (AccessibilityActionType::press);
  41. sendAccessibilityAutomationEvent (handler, UIA_SelectionItem_ElementSelectedEventId);
  42. return S_OK;
  43. }
  44. handler.getActions().invoke (AccessibilityActionType::toggle);
  45. handler.getActions().invoke (AccessibilityActionType::press);
  46. return S_OK;
  47. }
  48. JUCE_COMRESULT get_IsSelected (BOOL* pRetVal) override
  49. {
  50. return withCheckedComArgs (pRetVal, *this, [&]
  51. {
  52. const auto state = getHandler().getCurrentState();
  53. *pRetVal = isRadioButton ? state.isChecked() : state.isSelected();
  54. return S_OK;
  55. });
  56. }
  57. JUCE_COMRESULT get_SelectionContainer (IRawElementProviderSimple** pRetVal) override
  58. {
  59. return withCheckedComArgs (pRetVal, *this, [&]
  60. {
  61. if (! isRadioButton)
  62. if (auto* parent = getHandler().getParent())
  63. parent->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  64. return S_OK;
  65. });
  66. }
  67. JUCE_COMRESULT RemoveFromSelection() override
  68. {
  69. if (! isElementValid())
  70. return (HRESULT) UIA_E_ELEMENTNOTAVAILABLE;
  71. if (! isRadioButton)
  72. {
  73. const auto& handler = getHandler();
  74. if (handler.getCurrentState().isSelected())
  75. getHandler().getActions().invoke (AccessibilityActionType::toggle);
  76. }
  77. return S_OK;
  78. }
  79. JUCE_COMRESULT Select() override
  80. {
  81. if (! isElementValid())
  82. return (HRESULT) UIA_E_ELEMENTNOTAVAILABLE;
  83. AddToSelection();
  84. if (isElementValid() && ! isRadioButton)
  85. {
  86. const auto& handler = getHandler();
  87. if (auto* parent = handler.getParent())
  88. for (auto* child : parent->getChildren())
  89. if (child != &handler && child->getCurrentState().isSelected())
  90. child->getActions().invoke (AccessibilityActionType::toggle);
  91. }
  92. return S_OK;
  93. }
  94. private:
  95. const bool isRadioButton;
  96. //==============================================================================
  97. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIASelectionItemProvider)
  98. };
  99. //==============================================================================
  100. class UIASelectionProvider : public UIAProviderBase,
  101. public ComBaseClassHelper<ComTypes::ISelectionProvider2>
  102. {
  103. public:
  104. using UIAProviderBase::UIAProviderBase;
  105. //==============================================================================
  106. JUCE_COMRESULT QueryInterface (REFIID iid, void** result) override
  107. {
  108. if (iid == __uuidof (IUnknown) || iid == __uuidof (ComTypes::ISelectionProvider))
  109. return castToType<ComTypes::ISelectionProvider> (result);
  110. if (iid == __uuidof (ComTypes::ISelectionProvider2))
  111. return castToType<ComTypes::ISelectionProvider2> (result);
  112. *result = nullptr;
  113. return E_NOINTERFACE;
  114. }
  115. //==============================================================================
  116. JUCE_COMRESULT get_CanSelectMultiple (BOOL* pRetVal) override
  117. {
  118. return withCheckedComArgs (pRetVal, *this, [&]
  119. {
  120. *pRetVal = isMultiSelectable();
  121. return S_OK;
  122. });
  123. }
  124. JUCE_COMRESULT get_IsSelectionRequired (BOOL* pRetVal) override
  125. {
  126. return withCheckedComArgs (pRetVal, *this, [&]
  127. {
  128. *pRetVal = getSelectedChildren().size() > 0 && ! isMultiSelectable();
  129. return S_OK;
  130. });
  131. }
  132. JUCE_COMRESULT GetSelection (SAFEARRAY** pRetVal) override
  133. {
  134. return withCheckedComArgs (pRetVal, *this, [&]
  135. {
  136. return addHandlersToArray (getSelectedChildren(), pRetVal);
  137. });
  138. }
  139. //==============================================================================
  140. JUCE_COMRESULT get_FirstSelectedItem (IRawElementProviderSimple** pRetVal) override
  141. {
  142. return withCheckedComArgs (pRetVal, *this, [&]
  143. {
  144. auto selectedChildren = getSelectedChildren();
  145. if (! selectedChildren.empty())
  146. selectedChildren.front()->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  147. return S_OK;
  148. });
  149. }
  150. JUCE_COMRESULT get_LastSelectedItem (IRawElementProviderSimple** pRetVal) override
  151. {
  152. return withCheckedComArgs (pRetVal, *this, [&]
  153. {
  154. auto selectedChildren = getSelectedChildren();
  155. if (! selectedChildren.empty())
  156. selectedChildren.back()->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  157. return S_OK;
  158. });
  159. }
  160. JUCE_COMRESULT get_CurrentSelectedItem (IRawElementProviderSimple** pRetVal) override
  161. {
  162. return withCheckedComArgs (pRetVal, *this, [&]
  163. {
  164. get_FirstSelectedItem (pRetVal);
  165. return S_OK;
  166. });
  167. }
  168. JUCE_COMRESULT get_ItemCount (int* pRetVal) override
  169. {
  170. return withCheckedComArgs (pRetVal, *this, [&]
  171. {
  172. *pRetVal = (int) getSelectedChildren().size();
  173. return S_OK;
  174. });
  175. }
  176. private:
  177. bool isMultiSelectable() const noexcept
  178. {
  179. return getHandler().getCurrentState().isMultiSelectable();
  180. }
  181. std::vector<const AccessibilityHandler*> getSelectedChildren() const
  182. {
  183. std::vector<const AccessibilityHandler*> selectedHandlers;
  184. for (auto* child : getHandler().getComponent().getChildren())
  185. if (auto* handler = child->getAccessibilityHandler())
  186. if (handler->getCurrentState().isSelected())
  187. selectedHandlers.push_back (handler);
  188. return selectedHandlers;
  189. }
  190. //==============================================================================
  191. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIASelectionProvider)
  192. };
  193. JUCE_END_IGNORE_WARNINGS_GCC_LIKE
  194. } // namespace juce