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.

257 lines
8.3KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - 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 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-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. JUCE_COMCLASS (ISelectionProvider2, "14f68475-ee1c-44f6-a869-d239381f0fe7") : public ISelectionProvider
  22. {
  23. JUCE_COMCALL get_FirstSelectedItem (IRawElementProviderSimple** retVal) = 0;
  24. JUCE_COMCALL get_LastSelectedItem (IRawElementProviderSimple** retVal) = 0;
  25. JUCE_COMCALL get_CurrentSelectedItem (IRawElementProviderSimple** retVal) = 0;
  26. JUCE_COMCALL get_ItemCount (int* retVal) = 0;
  27. };
  28. //==============================================================================
  29. class UIASelectionItemProvider : public UIAProviderBase,
  30. public ComBaseClassHelper<ISelectionItemProvider>
  31. {
  32. public:
  33. explicit UIASelectionItemProvider (AccessibilityNativeHandle* nativeHandle)
  34. : UIAProviderBase (nativeHandle),
  35. isRadioButton (getHandler().getRole() == AccessibilityRole::radioButton)
  36. {
  37. }
  38. //==============================================================================
  39. JUCE_COMRESULT AddToSelection() override
  40. {
  41. if (! isElementValid())
  42. return (HRESULT) UIA_E_ELEMENTNOTAVAILABLE;
  43. const auto& handler = getHandler();
  44. if (isRadioButton)
  45. {
  46. handler.getActions().invoke (AccessibilityActionType::press);
  47. sendAccessibilityAutomationEvent (handler, UIA_SelectionItem_ElementSelectedEventId);
  48. return S_OK;
  49. }
  50. handler.getActions().invoke (AccessibilityActionType::toggle);
  51. handler.getActions().invoke (AccessibilityActionType::press);
  52. return S_OK;
  53. }
  54. JUCE_COMRESULT get_IsSelected (BOOL* pRetVal) override
  55. {
  56. return withCheckedComArgs (pRetVal, *this, [&]
  57. {
  58. const auto state = getHandler().getCurrentState();
  59. *pRetVal = isRadioButton ? state.isChecked() : state.isSelected();
  60. return S_OK;
  61. });
  62. }
  63. JUCE_COMRESULT get_SelectionContainer (IRawElementProviderSimple** pRetVal) override
  64. {
  65. return withCheckedComArgs (pRetVal, *this, [&]
  66. {
  67. if (! isRadioButton)
  68. if (auto* parent = getHandler().getParent())
  69. parent->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  70. return S_OK;
  71. });
  72. }
  73. JUCE_COMRESULT RemoveFromSelection() override
  74. {
  75. if (! isElementValid())
  76. return (HRESULT) UIA_E_ELEMENTNOTAVAILABLE;
  77. if (! isRadioButton)
  78. {
  79. const auto& handler = getHandler();
  80. if (handler.getCurrentState().isSelected())
  81. getHandler().getActions().invoke (AccessibilityActionType::toggle);
  82. }
  83. return S_OK;
  84. }
  85. JUCE_COMRESULT Select() override
  86. {
  87. if (! isElementValid())
  88. return (HRESULT) UIA_E_ELEMENTNOTAVAILABLE;
  89. AddToSelection();
  90. if (isElementValid() && ! isRadioButton)
  91. {
  92. const auto& handler = getHandler();
  93. if (auto* parent = handler.getParent())
  94. for (auto* child : parent->getChildren())
  95. if (child != &handler && child->getCurrentState().isSelected())
  96. child->getActions().invoke (AccessibilityActionType::toggle);
  97. }
  98. return S_OK;
  99. }
  100. private:
  101. const bool isRadioButton;
  102. //==============================================================================
  103. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIASelectionItemProvider)
  104. };
  105. //==============================================================================
  106. class UIASelectionProvider : public UIAProviderBase,
  107. public ComBaseClassHelper<ISelectionProvider2>
  108. {
  109. public:
  110. explicit UIASelectionProvider (AccessibilityNativeHandle* nativeHandle)
  111. : UIAProviderBase (nativeHandle)
  112. {
  113. }
  114. //==============================================================================
  115. JUCE_COMRESULT QueryInterface (REFIID iid, void** result) override
  116. {
  117. if (iid == _uuidof (IUnknown) || iid == _uuidof (ISelectionProvider))
  118. return castToType<ISelectionProvider> (result);
  119. if (iid == _uuidof (ISelectionProvider2))
  120. return castToType<ISelectionProvider2> (result);
  121. *result = nullptr;
  122. return E_NOINTERFACE;
  123. }
  124. //==============================================================================
  125. JUCE_COMRESULT get_CanSelectMultiple (BOOL* pRetVal) override
  126. {
  127. return withCheckedComArgs (pRetVal, *this, [&]
  128. {
  129. *pRetVal = isMultiSelectable();
  130. return S_OK;
  131. });
  132. }
  133. JUCE_COMRESULT get_IsSelectionRequired (BOOL* pRetVal) override
  134. {
  135. return withCheckedComArgs (pRetVal, *this, [&]
  136. {
  137. *pRetVal = getSelectedChildren().size() > 0 && ! isMultiSelectable();
  138. return S_OK;
  139. });
  140. }
  141. JUCE_COMRESULT GetSelection (SAFEARRAY** pRetVal) override
  142. {
  143. return withCheckedComArgs (pRetVal, *this, [&]
  144. {
  145. return addHandlersToArray (getSelectedChildren(), pRetVal);
  146. });
  147. }
  148. //==============================================================================
  149. JUCE_COMRESULT get_FirstSelectedItem (IRawElementProviderSimple** pRetVal) override
  150. {
  151. return withCheckedComArgs (pRetVal, *this, [&]
  152. {
  153. auto selectedChildren = getSelectedChildren();
  154. if (! selectedChildren.empty())
  155. selectedChildren.front()->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  156. return S_OK;
  157. });
  158. }
  159. JUCE_COMRESULT get_LastSelectedItem (IRawElementProviderSimple** pRetVal) override
  160. {
  161. return withCheckedComArgs (pRetVal, *this, [&]
  162. {
  163. auto selectedChildren = getSelectedChildren();
  164. if (! selectedChildren.empty())
  165. selectedChildren.back()->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  166. return S_OK;
  167. });
  168. }
  169. JUCE_COMRESULT get_CurrentSelectedItem (IRawElementProviderSimple** pRetVal) override
  170. {
  171. return withCheckedComArgs (pRetVal, *this, [&]
  172. {
  173. get_FirstSelectedItem (pRetVal);
  174. return S_OK;
  175. });
  176. }
  177. JUCE_COMRESULT get_ItemCount (int* pRetVal) override
  178. {
  179. return withCheckedComArgs (pRetVal, *this, [&]
  180. {
  181. *pRetVal = (int) getSelectedChildren().size();
  182. return S_OK;
  183. });
  184. }
  185. private:
  186. bool isMultiSelectable() const noexcept
  187. {
  188. return getHandler().getCurrentState().isMultiSelectable();
  189. }
  190. std::vector<const AccessibilityHandler*> getSelectedChildren() const
  191. {
  192. std::vector<const AccessibilityHandler*> selectedHandlers;
  193. for (auto* child : getHandler().getComponent().getChildren())
  194. if (auto* handler = child->getAccessibilityHandler())
  195. if (handler->getCurrentState().isSelected())
  196. selectedHandlers.push_back (handler);
  197. return selectedHandlers;
  198. }
  199. //==============================================================================
  200. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIASelectionProvider)
  201. };
  202. JUCE_END_IGNORE_WARNINGS_GCC_LIKE
  203. } // namespace juce