/*
* Copyright(c) 2021 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.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Tizen.NUI;
namespace Tizen.NUI.BaseComponents
{
///
/// AccessibilityRange is used to store data related with Text.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public class AccessibilityRange
{
///
/// Start position in stored text.
///
public int StartOffset { get; set; } = 0;
///
/// End position in stored text.
///
public int EndOffset { get; set; } = 0;
///
/// Text content in stored text.
///
public string Content { get; set; } = "";
}
///
/// View is the base class for all views.
///
/// 3
public partial class View
{
///////////////////////////////////////////////////////////////////
// ****************** Accessibility Attributes ****************** //
///////////////////////////////////////////////////////////////////
///
/// Dictionary of accessibility attributes (key-value pairs of strings).
///
[EditorBrowsable(EditorBrowsableState.Never)]
public Dictionary AccessibilityAttributes { get; } = new Dictionary();
///
/// Dictionary of dynamically-evaluated accessibility attributes (key-value pairs of strings).
///
[EditorBrowsable(EditorBrowsableState.Never)]
public Dictionary> AccessibilityDynamicAttributes { get; } = new Dictionary>();
///////////////////////////////////////////////////////////////////
// ************************** Highlight ************************ //
///////////////////////////////////////////////////////////////////
///
/// Clears accessibility highlight.
///
/// True if cleared, otherwise false when it is not possible
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ClearAccessibilityHighlight()
{
bool result = Interop.ControlDevel.DaliToolkitDevelControlClearAccessibilityHighlight(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return result;
}
///
/// Grabs accessibility highlight.
///
/// True if cleared, otherwise false when it is not possible
[EditorBrowsable(EditorBrowsableState.Never)]
public bool GrabAccessibilityHighlight()
{
bool result = Interop.ControlDevel.DaliToolkitDevelControlGrabAccessibilityHighlight(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return result;
}
///
/// Flag to check whether this view is highlighted or not.
///
[EditorBrowsable(EditorBrowsableState.Never)]
protected bool IsHighlighted
{
get
{
return (this == Accessibility.Accessibility.GetCurrentlyHighlightedView());
}
}
///////////////////////////////////////////////////////////////////
// ****************** Accessibility Relations ******************* //
///////////////////////////////////////////////////////////////////
///
/// Creates relation between objects.
///
/// Object which will be in relation.
/// Relation type.
/// You must pass valid object. NULL could not be in relation.
[EditorBrowsable(EditorBrowsableState.Never)]
public void AppendAccessibilityRelation(View second, AccessibilityRelationType relation)
{
if (second is null)
{
throw new ArgumentNullException(nameof(second));
}
Interop.ControlDevel.DaliToolkitDevelControlAppendAccessibilityRelation(SwigCPtr, second.SwigCPtr, (int)relation);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Removes accessibility relation.
///
/// Object which will be removed in relation
/// Relation type
[EditorBrowsable(EditorBrowsableState.Never)]
public void RemoveAccessibilityRelation(View second, AccessibilityRelationType relation)
{
if (second is null)
{
throw new ArgumentNullException(nameof(second));
}
Interop.ControlDevel.DaliToolkitDevelControlRemoveAccessibilityRelation(SwigCPtr, second.SwigCPtr, (int)relation);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Removes all previously appended relations.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ClearAccessibilityRelations()
{
Interop.ControlDevel.DaliToolkitDevelControlClearAccessibilityRelations(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Gets accessibility collection connected with the current object.
///
/// A dictionary mapping a relation type to a set of objects in that relation
[EditorBrowsable(EditorBrowsableState.Never)]
public Dictionary> GetAccessibilityRelations()
{
var list = new List>();
var listHandle = GCHandle.Alloc(list);
var callback = new Interop.ControlDevel.GetAccessibilityRelationsCallback(GetAccessibilityRelationsCallback);
Interop.ControlDevel.DaliToolkitDevelControlGetAccessibilityRelations(SwigCPtr, callback, GCHandle.ToIntPtr(listHandle));
listHandle.Free();
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
var result = new Dictionary>();
foreach (var pair in list)
{
var key = (AccessibilityRelationType)pair.Key;
var value = this.GetInstanceSafely(pair.Value);
if (!result.ContainsKey(key))
{
result[key] = new List();
}
result[key].Add(value);
}
return result;
}
private static void GetAccessibilityRelationsCallback(int relationType, IntPtr relationTarget, IntPtr userData)
{
var handle = GCHandle.FromIntPtr(userData);
var list = (List>)handle.Target;
list.Add(new KeyValuePair(relationType, relationTarget));
}
///////////////////////////////////////////////////////////////////
// ********************* ReadingInfoType *********************** //
///////////////////////////////////////////////////////////////////
///
/// Sets accessibility reading information.
///
/// Reading information type
[EditorBrowsable(EditorBrowsableState.Never)]
public void SetAccessibilityReadingInfoTypes(AccessibilityReadingInfoTypes type)
{
Interop.ControlDevel.DaliToolkitDevelControlSetAccessibilityReadingInfoTypes(SwigCPtr, (int)type);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Gets accessibility reading information.
///
/// Reading information type
[EditorBrowsable(EditorBrowsableState.Never)]
public AccessibilityReadingInfoTypes GetAccessibilityReadingInfoTypes()
{
AccessibilityReadingInfoTypes result = (AccessibilityReadingInfoTypes)Interop.ControlDevel.DaliToolkitDevelControlGetAccessibilityReadingInfoTypes(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return result;
}
///////////////////////////////////////////////////////////////////
// ******************** Accessibility States ******************* //
///////////////////////////////////////////////////////////////////
///
/// Notifies sending notifications about the current states to accessibility clients.
///
///
/// In essence, this is equivalent to calling EmitAccessibilityStateChangedEvent in a loop for all specified states.
/// If recursive mode is specified, all children of the Accessibility object will also re-emit the states.
///
/// Accessibility States
/// Controls the notification strategy
[EditorBrowsable(EditorBrowsableState.Never)]
public void NotifyAccessibilityStatesChange(AccessibilityStates states, AccessibilityStatesNotifyMode notifyMode)
{
if (states is null)
{
throw new ArgumentNullException(nameof(states));
}
Interop.ControlDevel.DaliToolkitDevelControlNotifyAccessibilityStateChange(SwigCPtr, states.BitMask, (int)notifyMode);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Gets Accessibility States.
///
/// Accessibility States
[EditorBrowsable(EditorBrowsableState.Never)]
public AccessibilityStates GetAccessibilityStates()
{
var result = new AccessibilityStates { BitMask = Interop.ControlDevel.DaliToolkitDevelControlGetAccessibilityStates(SwigCPtr) };
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return result;
}
///////////////////////////////////////////////////////////////////
// ************************ Accessible ************************* //
///////////////////////////////////////////////////////////////////
///
/// Emits accessibility property changed event.
///
/// Property changed event
[EditorBrowsable(EditorBrowsableState.Never)]
public void EmitAccessibilityEvent(AccessibilityPropertyChangeEvent changeEvent)
{
Interop.ControlDevel.DaliAccessibilityEmitAccessibilityEvent(SwigCPtr, Convert.ToInt32(changeEvent));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Emits accessibility states changed event.
///
/// Accessibility state
/// True if the state is set or enabled, otherwise false
[EditorBrowsable(EditorBrowsableState.Never)]
public void EmitAccessibilityStateChangedEvent(AccessibilityState state, bool equal)
{
Interop.ControlDevel.DaliAccessibilityEmitAccessibilityStateChangedEvent(SwigCPtr, (int)state, Convert.ToInt32(equal));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Emits accessibility text inserted event.
///
/// Text cursor position
/// Text length
/// Inserted text content
[EditorBrowsable(EditorBrowsableState.Never)]
public void EmitTextInsertedEvent(int cursorPosition, int length, string content)
{
Interop.ControlDevel.DaliAccessibilityEmitTextInsertedEvent(SwigCPtr, cursorPosition, length, content);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Emits accessibility text deleted event.
///
/// Text cursor position
/// Text length
/// Inserted text content
[EditorBrowsable(EditorBrowsableState.Never)]
public void EmitTextDeletedEvent(int cursorPosition, int length, string content)
{
Interop.ControlDevel.DaliAccessibilityEmitTextDeletedEvent(SwigCPtr, cursorPosition, length, content);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Emits accessibility text cursor moved event.
///
/// The new cursor position
[EditorBrowsable(EditorBrowsableState.Never)]
public void EmitTextCursorMovedEvent(int cursorPosition)
{
Interop.ControlDevel.DaliAccessibilityEmitTextCursorMovedEvent(SwigCPtr, cursorPosition);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Modifiable collection of suppressed AT-SPI events (D-Bus signals).
///
[EditorBrowsable(EditorBrowsableState.Never)]
public AccessibilityEvents AccessibilitySuppressedEvents
{
get
{
return new AccessibilityEvents { Owner = this };
}
}
///////////////////////////////////////////////////////////////////
// ************************** Bridge *************************** //
///////////////////////////////////////////////////////////////////
///
/// Registers component as a source of an accessibility "default label".
/// The "Default label" is a text that could be read by screen-reader immediately
/// after the navigation context has changed (window activates, popup shows up, tab changes)
/// and before first UI element is highlighted.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void RegisterDefaultLabel()
{
Interop.ControlDevel.DaliAccessibilityBridgeRegisterDefaultLabel(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Unregisters component that has been registered previously as a source of an accessibility "default label".
/// The "Default label" is a text that could be read by screen-reader immediately
/// after the navigation context has changed (window activates, popup shows up, tab changes)
/// and before first UI element is highlighted.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void UnregisterDefaultLabel()
{
Interop.ControlDevel.DaliAccessibilityBridgeUnregisterDefaultLabel(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected override void Dispose(bool disposing)
{
if (disposed)
{
return;
}
internalName = null;
if (disposing == false)
{
if (IsNativeHandleInvalid() || SwigCMemOwn == false)
{
// at this case, implicit nor explicit dispose is not required. No native object is made.
disposed = true;
return;
}
}
if (disposing)
{
Unparent();
}
base.Dispose(disposing);
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected static readonly string AccessibilityActivateAction = "activate";
[EditorBrowsable(EditorBrowsableState.Never)]
protected static readonly string AccessibilityReadingSkippedAction = "ReadingSkipped";
[EditorBrowsable(EditorBrowsableState.Never)]
protected static readonly string AccessibilityReadingCancelledAction = "ReadingCancelled";
[EditorBrowsable(EditorBrowsableState.Never)]
protected static readonly string AccessibilityReadingStoppedAction = "ReadingStopped";
[EditorBrowsable(EditorBrowsableState.Never)]
protected static readonly string AccessibilityReadingPausedAction = "ReadingPaused";
[EditorBrowsable(EditorBrowsableState.Never)]
protected static readonly string AccessibilityReadingResumedAction = "ReadingResumed";
[EditorBrowsable(EditorBrowsableState.Never)]
private static readonly string[] AccessibilityActions = {
AccessibilityActivateAction,
AccessibilityReadingSkippedAction,
AccessibilityReadingCancelledAction,
AccessibilityReadingStoppedAction,
AccessibilityReadingPausedAction,
AccessibilityReadingResumedAction,
};
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual string AccessibilityGetName()
{
return "";
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual string AccessibilityGetDescription()
{
return "";
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual bool AccessibilityDoAction(string name)
{
if (name == AccessibilityActivateAction)
{
if (ActivateSignal?.Empty() == false)
{
ActivateSignal?.Emit();
return true;
}
else
{
return OnAccessibilityActivated();
}
}
else if (name == AccessibilityReadingSkippedAction)
{
if (ReadingSkippedSignal?.Empty() == false)
{
ReadingSkippedSignal?.Emit();
return true;
}
else
{
return OnAccessibilityReadingSkipped();
}
}
else if (name == AccessibilityReadingCancelledAction)
{
if (ReadingCancelledSignal?.Empty() == false)
{
ReadingCancelledSignal?.Emit();
return true;
}
else
{
return OnAccessibilityReadingCancelled();
}
}
else if (name == AccessibilityReadingStoppedAction)
{
if (ReadingStoppedSignal?.Empty() == false)
{
ReadingStoppedSignal?.Emit();
return true;
}
else
{
return OnAccessibilityReadingStopped();
}
}
else if (name == AccessibilityReadingPausedAction)
{
if (ReadingPausedSignal?.Empty() == false)
{
ReadingPausedSignal?.Emit();
return true;
}
else
{
return OnAccessibilityReadingPaused();
}
}
else if (name == AccessibilityReadingResumedAction)
{
if (ReadingResumedSignal?.Empty() == false)
{
ReadingResumedSignal?.Emit();
return true;
}
else
{
return OnAccessibilityReadingResumed();
}
}
else
{
return false;
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual AccessibilityStates AccessibilityCalculateStates()
{
var states = AccessibilityInitialStates;
states[AccessibilityState.Focused] = this.State == States.Focused;
states[AccessibilityState.Enabled] = this.State != States.Disabled;
states[AccessibilityState.Sensitive] = this.Sensitive;
return states;
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual int AccessibilityGetActionCount()
{
return AccessibilityActions.Length;
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual string AccessibilityGetActionName(int index)
{
if (index >= 0 && index < AccessibilityActions.Length)
{
return AccessibilityActions[index];
}
else
{
return "";
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual bool AccessibilityIsScrollable()
{
return false;
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual bool AccessibilityScrollToChild(View child)
{
return false;
}
///
/// This method is called when the control accessibility is activated.
/// Derived classes should override this to perform custom accessibility activation.
///
/// True if this control can perform accessibility activation.
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual bool OnAccessibilityActivated()
{
return FocusManager.Instance.SetCurrentFocusView(this);
}
///
/// This method is called when reading is skipped.
///
/// True if information was served.
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual bool OnAccessibilityReadingSkipped()
{
return false;
}
///
/// This method is called when reading is cancelled.
///
/// True if information was served.
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual bool OnAccessibilityReadingCancelled()
{
return false;
}
///
/// This method is called when reading is stopped.
///
/// True if information was served.
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual bool OnAccessibilityReadingStopped()
{
return false;
}
///
/// This method is called when reading was paused.
///
/// True if information was served.
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual bool OnAccessibilityReadingPaused()
{
return false;
}
///
/// This method is called when reading is resumed.
///
/// True if information was served.
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual bool OnAccessibilityReadingResumed()
{
return false;
}
}
}