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.

239 lines
7.6KB

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