[NUI] Add some accessibility version 2 features for new components (#6907)
authorSeoyeon2Kim <34738918+Seoyeon2Kim@users.noreply.github.com>
Wed, 28 May 2025 06:07:30 +0000 (15:07 +0900)
committerJaehyun Cho <jaehyun0cho@gmail.com>
Thu, 29 May 2025 05:08:24 +0000 (14:08 +0900)
* [NUI] Add some accessibility features for new components

- Introduce essential additions to support accessibility features for OneUI Components.
 1) AccessibilityState2
 2) AccessibilityRole2
 3) AccessibilityIsModal

Signed-off-by: Seoyeon Kim <seoyeon2.kim@samsung.com>
* Modify the naming

Signed-off-by: Seoyeon Kim <seoyeon2.kim@samsung.com>
* Update the description of `AccessibilityStatesV2.this`

Signed-off-by: Seoyeon Kim <seoyeon2.kim@samsung.com>
* Add some test cases

Signed-off-by: Seoyeon Kim <seoyeon2.kim@samsung.com>
* Spilt the files according to their own roles

- ViewAccessibilityV2.cs / ViewAccessibilityRoleV2.cs / ViewAccessibilityStatesV2.cs

Signed-off-by: Seoyeon Kim <seoyeon2.kim@samsung.com>
---------

Signed-off-by: Seoyeon Kim <seoyeon2.kim@samsung.com>
src/Tizen.NUI/src/internal/Interop/Interop.ViewProperty.cs
src/Tizen.NUI/src/public/BaseComponents/ViewAccessibilityRoleV2.cs [new file with mode: 0755]
src/Tizen.NUI/src/public/BaseComponents/ViewAccessibilityStatesV2.cs [new file with mode: 0755]
src/Tizen.NUI/src/public/BaseComponents/ViewAccessibilityV2.cs [new file with mode: 0755]
src/Tizen.NUI/src/public/BaseComponents/ViewEnum.cs
test/Tizen.NUI.Devel.Tests.Ubuntu/Tizen.NUI.Devel.Tests/testcase/public/TSView.cs

index 9e17e8829d24d3a77d591a16afa090c451bb2fe7..a5c2d07320b96851bb323230fc4b5fd9a5a6d2c4 100755 (executable)
@@ -93,6 +93,12 @@ namespace Tizen.NUI
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_View_Property_AUTOMATION_ID_get")]
             public static extern int AutomationIdGet();
 
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_View_Property_ACCESSIBILITY_STATES_get")]
+            public static extern int AccessibilityStateGet();
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_View_Property_ACCESSIBILITY_IS_MODAL_get")]
+            public static extern int AccessibilityIsModalGet();
+
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_View_Property_OFFSCREEN_RENDERING_get")]
             public static extern int OffScreenRenderingGet();
 
diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewAccessibilityRoleV2.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewAccessibilityRoleV2.cs
new file mode 100755 (executable)
index 0000000..410f606
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright(c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using System.ComponentModel;
+using Tizen.NUI;
+
+namespace Tizen.NUI.BaseComponents
+{
+    /// <summary>
+    /// Specifies the role of an accessible object.
+    /// </summary>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public enum AccessibilityRoleV2
+    {
+        /// <summary>
+        /// A slider
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Adjustable = 200,
+        /// <summary>
+        /// An alert
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Alert,
+        /// <summary>
+        /// A button
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Button,
+        /// <summary>
+        /// A check box
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        CheckBox,
+        /// <summary>
+        /// A combo box
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        ComboBox,
+        /// <summary>
+        /// A container
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Container,
+        /// <summary>
+        /// A dialog
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Dialog,
+        /// <summary>
+        /// An entry
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Entry,
+        /// <summary>
+        /// A header
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Header,
+        /// <summary>
+        /// An Image
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Image,
+        /// <summary>
+        /// A link
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Link,
+        /// <summary>
+        /// A list
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        List,
+        /// <summary>
+        /// An item of the list
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        ListItem,
+        /// <summary>
+        /// A menu
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Menu,
+        /// <summary>
+        /// A menu bar
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        MenuBar,
+        /// <summary>
+        /// An item of the menu
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        MenuItem,
+        /// <summary>
+        /// None
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        None,
+        /// <summary>
+        /// A password text
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        PasswordText,
+        /// <summary>
+        /// A popup menu
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        PopupMenu,
+        /// <summary>
+        /// A progress bar
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        ProgressBar,
+        /// <summary>
+        /// A radio button
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        RadioButton,
+        /// <summary>
+        /// A scroll bar
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        ScrollBar,
+        /// <summary>
+        /// A spin button
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        SpinButton,
+        /// <summary>
+        /// A tab
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Tab,
+        /// <summary>
+        /// A tab list
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        TabList,
+        /// <summary>
+        /// A text
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Text,
+        /// <summary>
+        /// A toggle button
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        ToggleButton,
+        /// <summary>
+        /// a tool bar
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Toolbar,
+    }
+}
diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewAccessibilityStatesV2.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewAccessibilityStatesV2.cs
new file mode 100755 (executable)
index 0000000..caed57a
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright(c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using System.ComponentModel;
+using Tizen.NUI;
+
+namespace Tizen.NUI.BaseComponents
+{
+    /// <summary>
+    /// AccessibilityStateV2 is an enumeration that represents the states of the view to send to accessibility service.
+    /// </summary>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public enum AccessibilityStateV2
+    {
+        /// <summary>
+        /// Indicates whether the view is enabled or not.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Enabled = 0,
+        /// <summary>
+        /// Indicates whether a selectable element is currently selected or not.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Selected,
+        /// <summary>
+        /// Indicates the state of a checkable element.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Checked,
+        /// <summary>
+        /// Indicates whether an element is currently busy or not.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Busy,
+        /// <summary>
+        /// Indicates whether an expandable element is currently expanded or collapsed.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        Expanded
+    }
+
+    /// <summary>
+    /// The AccessibilityStatesV2 structure represents a set of states of the view to communicate to accessibility service.
+    /// </summary>
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public struct AccessibilityStatesV2
+    {
+        const uint c_on = 1;
+        private uint _bitMask;
+
+        /// <summary>
+        /// Gets or sets the value of the specified accessibility state flag using bitmask operations.
+        /// </summary>
+        /// <param name="state">The <see cref="AccessibilityStateV2"/> enum value representing the accessibility state to check or modify.</param>
+        /// <returns>
+        /// <c>true</c> if the specified state flag is set in the bitmask; otherwise, <c>false</c>.
+        /// </returns>
+        /// <remarks>
+        /// This indexer uses bitwise operations to efficiently store and retrieve multiple boolean state flags
+        /// in a single integer field (_bitMask). Each state corresponds to a specific bit position determined
+        /// by its enum value.
+        /// </remarks>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool this[AccessibilityStateV2 state]
+        {
+            get
+            {
+                return Convert.ToBoolean(_bitMask & (c_on << (int)state));
+            }
+            set
+            {
+                if (value)
+                {
+                    _bitMask |= (c_on << (int)state);
+                }
+                else
+                {
+                    _bitMask &= ~(c_on << (int)state);
+                }
+            }
+        }
+
+        AccessibilityStatesV2(int states)
+        {
+            _bitMask = (uint)states;
+        }
+
+        /// <summary>
+        /// Converts an <see cref="AccessibilityStatesV2"/> enumeration value to an integer.
+        /// </summary>
+        /// <param name="state">The <see cref="AccessibilityStatesV2"/> value to convert.</param>
+        /// <returns>The integer representation of the specified <see cref="AccessibilityStatesV2"/> value.</returns>
+        /// <remarks>
+        /// This explicit operator retrieves the internal bitmask value of the <see cref="AccessibilityStatesV2"/> enumeration,
+        /// which represents the combined state flags in a single integer.
+        /// </remarks>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static explicit operator int(AccessibilityStatesV2 state)
+        {
+            return (int)state._bitMask;
+        }
+
+        /// <summary>
+        /// Converts an integer to an <see cref="AccessibilityStatesV2"/> enumeration value.
+        /// </summary>
+        /// <param name="states">The integer value to convert.</param>
+        /// <returns>A new instance of <see cref="AccessibilityStatesV2"/> initialized with the specified integer value.</returns>
+        /// <remarks>
+        /// This explicit operator creates a new <see cref="AccessibilityStatesV2"/> object using the provided integer value,
+        /// which is interpreted as a bitmask representing multiple state flags.
+        /// </remarks>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static explicit operator AccessibilityStatesV2(int states)
+        {
+            return new AccessibilityStatesV2(states);
+        }
+    }
+}
diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewAccessibilityV2.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewAccessibilityV2.cs
new file mode 100755 (executable)
index 0000000..0823275
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright(c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using System.ComponentModel;
+using Tizen.NUI;
+
+namespace Tizen.NUI.BaseComponents
+{
+    /// <summary>
+    /// View is the base class for all views.
+    /// </summary>
+    /// <since_tizen> 3 </since_tizen>
+    public partial class View
+    {
+        ///////////////////////////////////////////////////////////////////
+        // ************ Accessibility Methods for Version 2 ************ //
+        ///////////////////////////////////////////////////////////////////
+
+        /// <summary>
+        /// Gets the AccessibilityStatesV2 property of the view.
+        /// </summary>
+        /// <returns>The states<see cref="AccessibilityStatesV2"/> of the view</returns>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public AccessibilityStatesV2 GetAccessibilityStatesV2()
+        {
+            return (AccessibilityStatesV2)Object.InternalGetPropertyInt(SwigCPtr, Property.AccessibilityState);
+        }
+
+        /// <summary>
+        /// Sets the AccessibilityStatesV2 property of the view.
+        /// </summary>
+        /// <param name="states">The states<see cref="AccessibilityStatesV2"/> value to set.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void SetAccessibilityStatesV2(AccessibilityStatesV2 states)
+        {
+            Object.InternalSetPropertyInt(SwigCPtr, Property.AccessibilityState, (int)states);
+        }
+
+        /// <summary>
+        /// Gets the accessibility role of the view.
+        /// </summary>
+        /// <returns>The role<see cref="AccessibilityRoleV2"/> of the view</returns>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public AccessibilityRoleV2 GetAccessibilityRoleV2()
+        {
+            return (AccessibilityRoleV2)Object.InternalGetPropertyInt(SwigCPtr, Property.AccessibilityRole);
+        }
+
+        /// <summary>
+        /// Sets the accessibiltiy role of the view.
+        /// </summary>
+        /// <param name="role">The role<see cref="AccessibilityRoleV2"/> value to set.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void SetAccessibilityRoleV2(AccessibilityRoleV2 role)
+        {
+            Object.InternalSetPropertyInt(SwigCPtr, Property.AccessibilityRole, (int)role);
+        }
+
+        /// <summary>
+        /// Controls whether the view is modal or not.
+        /// </summary>
+        /// <remarks>
+        /// False by default.
+        /// </remarks>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool AccessibilityIsModal
+        {
+            get
+            {
+                return Object.InternalGetPropertyBool(SwigCPtr, Property.AccessibilityIsModal);
+            }
+            set
+            {
+                Object.InternalSetPropertyBool(SwigCPtr, Property.AccessibilityIsModal, value);
+            }
+        }
+
+    }
+}
index f6cdeeb82c02379212e44686c93eb6ee6dcb99cc..73a0b1a7de230dedb9a5464b89c5ff08223b2708 100755 (executable)
@@ -289,6 +289,8 @@ namespace Tizen.NUI.BaseComponents
             internal static readonly int DispatchKeyEvents = Interop.ViewProperty.DispatchKeyEventsGet();
             internal static readonly int AccessibilityHidden = Interop.ViewProperty.AccessibilityHiddenGet();
             internal static readonly int AutomationId = Interop.ViewProperty.AutomationIdGet();
+            internal static readonly int AccessibilityState = Interop.ViewProperty.AccessibilityStateGet();
+            internal static readonly int AccessibilityIsModal = Interop.ViewProperty.AccessibilityIsModalGet();
             internal static readonly int UpdateAreaHint = Interop.ActorProperty.UpdateAreaHintGet();
             internal static readonly int DispatchTouchMotion = Interop.ActorProperty.DispatchTouchMotionGet();
             internal static readonly int DispatchHoverMotion = Interop.ActorProperty.DispatchHoverMotionGet();
index 3a2ecb63dbb77dde501fead147b705d6427af25f..f6c9de53bc7cbd9595e340c8ca76cde5cfba2f7f 100644 (file)
@@ -226,5 +226,63 @@ namespace Tizen.NUI.Devel.Tests
 
             testView.Dispose();
         }
+
+        [Test]
+        [Category("P1")]
+        [Description("Verify SetAccessibilityStatesV2 and GetAccessibilityStatesV2 functionality")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View.GetAccessibilityStatesV2 M")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MR")]
+        [Property("AUTHOR", "seoyeon2.kim@samsung.com")]
+        public void AccessibilityStatesV2_SetAndGet_ReturnsCorrectState()
+        {
+            /* TEST CODE */
+            var testView = new View();
+            var expectedStates = new AccessibilityStatesV2();
+            expectedStates[AccessibilityStateV2.Enabled] = true;
+            testView.SetAccessibilityStatesV2(expectedStates);
+
+            var actualStates = testView.GetAccessibilityStatesV2();
+            Assert.AreEqual(true, actualStates[AccessibilityStateV2.Enabled], "View AccessibilityStateV2.Enabled should be true.");
+
+            testView.Dispose();
+        }
+
+        [Test]
+        [Category("P1")]
+        [Description("Verify SetAccessibilityRoleV2 and GetAccessibilityRoleV2 functionality")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View.GetAccessibilityRoleV2 M")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "MR")]
+        [Property("AUTHOR", "seoyeon2.kim@samsung.com")]
+        public void AccessibilityRoleV2_SetAndGet_ReturnsCorrectRole()
+        {
+            /* TEST CODE */
+            var testView = new View();
+            testView.SetAccessibilityRoleV2(AccessibilityRoleV2.Button);
+
+            var actualRole = testView.GetAccessibilityRoleV2();
+            Assert.AreEqual(AccessibilityRoleV2.Button, actualRole, "actualRole should be AccessibilityRoleV2.Button.");
+
+            testView.Dispose();
+        }
+
+        [Test]
+        [Category("P1")]
+        [Description("Get value test for View.AccessibilityIsModal")]
+        [Property("SPEC", "Tizen.NUI.BaseComponents.View.AccessibilityIsModal")]
+        [Property("SPEC_URL", "-")]
+        [Property("CRITERIA", "PRW")]
+        [Property("AUTHOR", "seoyeon2.kim@samsung.com")]
+        public void AccessibilityIsModal_GET_SET_VALUE()
+        {
+            /* TEST CODE */
+            View testView = new View();
+
+            testView.AccessibilityIsModal = true;
+            Assert.AreEqual(true, testView.AccessibilityIsModal, "Should get equal bool value what we set before");
+
+            testView.Dispose();
+        }
     }
 }