1use accesskit::Role;
2use bevy_a11y::AccessibilityNode;
3use bevy_app::{App, Plugin, PostUpdate};
4use bevy_ecs::{
5 change_detection::DetectChanges,
6 component::Component,
7 entity::Entity,
8 hierarchy::{ChildOf, Children},
9 lifecycle::RemovedComponents,
10 observer::On,
11 query::{Added, Changed, Has, Or, With},
12 reflect::ReflectComponent,
13 schedule::IntoScheduleConfigs,
14 system::{Commands, Query, Res, ResMut},
15 template::FromTemplate,
16};
17use bevy_input::{
18 keyboard::{KeyCode, KeyboardInput},
19 ButtonState,
20};
21use bevy_input_focus::{
22 tab_navigation::TabIndex, FocusCause, FocusedInput, InputFocus, InputFocusSystems,
23 InputFocusVisible,
24};
25use bevy_picking::{events::PointerClick, pointer::PointerButton};
26use bevy_reflect::{prelude::ReflectDefault, Reflect};
27use bevy_ui::{InteractionDisabled, Selectable, Selected};
28
29use crate::ControlOrientation;
30
31#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TabActivation {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
TabActivation::Manual => "Manual",
TabActivation::Automatic => "Automatic",
})
}
}Debug, #[automatically_derived]
impl ::core::default::Default for TabActivation {
#[inline]
fn default() -> Self { Self::Manual }
}Default, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for TabActivation { }
#[automatically_derived]
impl ::core::clone::Clone for TabActivation {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TabActivation { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for TabActivation { }
#[automatically_derived]
impl ::core::cmp::PartialEq for TabActivation {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for TabActivation { }Eq, const _: () =
{
impl bevy_reflect::GetTypeRegistration for TabActivation where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert(<bevy_reflect::ReflectFromPtr as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.insert(<bevy_reflect::ReflectFromReflect as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.register_type_data_with::<ReflectDefault, Self,
_>(());
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {}
}
impl bevy_reflect::Typed for TabActivation where {
#[inline(never)]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(#[inline(never)] ||
{
bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Manual")),
bevy_reflect::enums::VariantInfo::Unit(bevy_reflect::enums::UnitVariantInfo::new("Automatic"))]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for TabActivation where {
fn type_path() -> &'static str {
"bevy_ui_widgets::tabs::TabActivation"
}
fn short_type_path() -> &'static str { "TabActivation" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("TabActivation")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_ui_widgets::tabs".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_ui_widgets::tabs")
}
}
impl bevy_reflect::Reflect for TabActivation where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
#[allow(non_upper_case_globals)]
const _: () =
{
static __INVENTORY: ::inventory::Node =
::inventory::Node {
value: &{
bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<TabActivation
as
bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
},
next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
};
#[link_section = ".text.startup"]
unsafe extern "C" fn __ctor() {
unsafe {
::inventory::ErasedNode::submit(__INVENTORY.value,
&__INVENTORY)
}
}
#[used]
#[link_section = ".init_array"]
static __CTOR: unsafe extern "C" fn() = __ctor;
};
impl bevy_reflect::enums::Enum for TabActivation where {
fn field(&self, __name_param: &str)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn field_at(&self, __index_param: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn field_mut(&mut self, __name_param: &str)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn field_at_mut(&mut self, __index_param: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match self { _ => ::core::option::Option::None, }
}
fn index_of(&self, __name_param: &str)
-> ::core::option::Option<usize> {
match self { _ => ::core::option::Option::None, }
}
fn name_at(&self, __index_param: usize)
-> ::core::option::Option<&str> {
match self { _ => ::core::option::Option::None, }
}
fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
bevy_reflect::enums::VariantFieldIter::new(self)
}
#[inline]
fn field_len(&self) -> usize {
match self {
TabActivation::Manual { .. } => 0usize,
TabActivation::Automatic { .. } => 0usize,
_ => 0,
}
}
#[inline]
fn variant_name(&self) -> &str {
match self {
TabActivation::Manual { .. } => "Manual",
TabActivation::Automatic { .. } => "Automatic",
_ =>
::core::panicking::panic("internal error: entered unreachable code"),
}
}
#[inline]
fn variant_index(&self) -> usize {
match self {
TabActivation::Manual { .. } => 0usize,
TabActivation::Automatic { .. } => 1usize,
_ =>
::core::panicking::panic("internal error: entered unreachable code"),
}
}
#[inline]
fn variant_type(&self) -> bevy_reflect::enums::VariantType {
match self {
TabActivation::Manual { .. } =>
bevy_reflect::enums::VariantType::Unit,
TabActivation::Automatic { .. } =>
bevy_reflect::enums::VariantType::Unit,
_ =>
::core::panicking::panic("internal error: entered unreachable code"),
}
}
fn to_dynamic_enum(&self)
->
::core::result::Result<bevy_reflect::enums::DynamicEnum,
bevy_reflect::ReflectCloneError> {
bevy_reflect::enums::DynamicEnum::try_from_ref::<Self>(self)
}
}
impl bevy_reflect::PartialReflect for TabActivation where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self,
__value_param: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::Enum(__value_param) =
bevy_reflect::PartialReflect::reflect_ref(__value_param) {
if bevy_reflect::enums::Enum::variant_name(self) ==
bevy_reflect::enums::Enum::variant_name(__value_param) {
match bevy_reflect::enums::Enum::variant_type(__value_param)
{
bevy_reflect::enums::VariantType::Struct => {
for field in
bevy_reflect::enums::Enum::iter_fields(__value_param) {
let name = field.name().unwrap();
if let ::core::option::Option::Some(v) =
bevy_reflect::enums::Enum::field_mut(self, name) {
bevy_reflect::PartialReflect::try_apply(v, field.value())?;
}
}
}
bevy_reflect::enums::VariantType::Tuple => {
for (index, field) in
::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
{
if let ::core::option::Option::Some(v) =
bevy_reflect::enums::Enum::field_at_mut(self, index) {
bevy_reflect::PartialReflect::try_apply(v, field.value())?;
}
}
}
_ => {}
}
} else {
match bevy_reflect::enums::Enum::variant_name(__value_param)
{
"Manual" => { *self = TabActivation::Manual {} }
"Automatic" => { *self = TabActivation::Automatic {} }
name => {
return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
variant_name: ::core::convert::Into::into(name),
});
}
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
to_kind: bevy_reflect::ReflectKind::Enum,
});
}
::core::result::Result::Ok(())
}
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::Enum
}
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::Enum(self)
}
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::Enum(self)
}
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::Enum(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_hash(&self) -> ::core::option::Option<u64> {
(bevy_reflect::enums::enum_hash)(self)
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
let value =
<dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
if let ::core::option::Option::Some(value) = value {
::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
value))
} else { ::core::option::Option::Some(false) }
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::enums::enum_partial_cmp)(self, value)
}
#[inline]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
}
}
impl bevy_reflect::FromReflect for TabActivation where {
fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::Enum(__param0) =
bevy_reflect::PartialReflect::reflect_ref(__param0) {
match bevy_reflect::enums::Enum::variant_name(__param0) {
"Manual" =>
::core::option::Option::Some(TabActivation::Manual {}),
"Automatic" =>
::core::option::Option::Some(TabActivation::Automatic {}),
name => ::core::option::Option::None,
}
} else { ::core::option::Option::None }
}
}
};Reflect)]
33#[reflect(Default, Clone, PartialEq)]
34pub enum TabActivation {
35 #[default]
37 Manual,
38 Automatic,
40}
41
42#[derive(#[doc =
"**Required Components**: [`AccessibilityNode`], [`SelectedTab`]. \n\n A component's Required Components are inserted whenever it is inserted. Note that this will also insert the required components _of_ the required components, recursively, in depth-first order."]
impl bevy_ecs::component::Component for TabList where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {
required_components.register_required::<AccessibilityNode>(||
{
let x: AccessibilityNode =
(||
AccessibilityNode(accesskit::Node::new(Role::TabList)))().into();
x
});
required_components.register_required::<SelectedTab>(<SelectedTab as
::core::default::Default>::default);
}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component, #[automatically_derived]
impl ::core::fmt::Debug for TabList {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "TabList",
"orientation", &self.orientation, "activation", &&self.activation)
}
}Debug, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for TabList { }
#[automatically_derived]
impl ::core::clone::Clone for TabList {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<ControlOrientation>;
let _: ::core::clone::AssertParamIsClone<TabActivation>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TabList { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for TabList { }
#[automatically_derived]
impl ::core::cmp::PartialEq for TabList {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.orientation == other.orientation &&
self.activation == other.activation
}
}PartialEq, const _: () =
{
impl bevy_reflect::GetTypeRegistration for TabList where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert(<bevy_reflect::ReflectFromPtr as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.insert(<bevy_reflect::ReflectFromReflect as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.register_type_data_with::<ReflectComponent, Self,
_>(());
registration.register_type_data_with::<ReflectDefault, Self,
_>(());
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {
<ControlOrientation as
bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
<TabActivation as
bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
}
}
impl bevy_reflect::Typed for TabList where {
#[inline(never)]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(#[inline(never)] ||
{
bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<ControlOrientation>("orientation"),
bevy_reflect::NamedField::new::<TabActivation>("activation")]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for TabList where {
fn type_path() -> &'static str {
"bevy_ui_widgets::tabs::TabList"
}
fn short_type_path() -> &'static str { "TabList" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("TabList")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_ui_widgets::tabs".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_ui_widgets::tabs")
}
}
impl bevy_reflect::Reflect for TabList where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
#[allow(non_upper_case_globals)]
const _: () =
{
static __INVENTORY: ::inventory::Node =
::inventory::Node {
value: &{
bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<TabList
as
bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
},
next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
};
#[link_section = ".text.startup"]
unsafe extern "C" fn __ctor() {
unsafe {
::inventory::ErasedNode::submit(__INVENTORY.value,
&__INVENTORY)
}
}
#[used]
#[link_section = ".init_array"]
static __CTOR: unsafe extern "C" fn() = __ctor;
};
impl bevy_reflect::structs::Struct for TabList where {
fn field(&self, name: &str)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match name {
"orientation" =>
::core::option::Option::Some(&self.orientation),
"activation" =>
::core::option::Option::Some(&self.activation),
_ => ::core::option::Option::None,
}
}
fn field_mut(&mut self, name: &str)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match name {
"orientation" =>
::core::option::Option::Some(&mut self.orientation),
"activation" =>
::core::option::Option::Some(&mut self.activation),
_ => ::core::option::Option::None,
}
}
fn field_at(&self, index: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&self.orientation),
1usize => ::core::option::Option::Some(&self.activation),
_ => ::core::option::Option::None,
}
}
fn field_at_mut(&mut self, index: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match index {
0usize =>
::core::option::Option::Some(&mut self.orientation),
1usize =>
::core::option::Option::Some(&mut self.activation),
_ => ::core::option::Option::None,
}
}
fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
match index {
0usize => ::core::option::Option::Some("orientation"),
1usize => ::core::option::Option::Some("activation"),
_ => ::core::option::Option::None,
}
}
fn index_of_name(&self, name: &str)
-> ::core::option::Option<usize> {
match name {
"orientation" => ::core::option::Option::Some(0usize),
"activation" => ::core::option::Option::Some(1usize),
_ => ::core::option::Option::None,
}
}
fn field_len(&self) -> usize { 2usize }
fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
bevy_reflect::structs::FieldIter::new(self)
}
fn to_dynamic_struct(&self)
->
::core::result::Result<bevy_reflect::structs::DynamicStruct,
bevy_reflect::ReflectCloneError> {
let mut dynamic: bevy_reflect::structs::DynamicStruct =
::core::default::Default::default();
dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
dynamic.insert_boxed("orientation",
bevy_reflect::PartialReflect::to_dynamic(&self.orientation)?);
dynamic.insert_boxed("activation",
bevy_reflect::PartialReflect::to_dynamic(&self.activation)?);
::core::result::Result::Ok(dynamic)
}
}
impl bevy_reflect::PartialReflect for TabList where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::Struct(struct_value) =
bevy_reflect::PartialReflect::reflect_ref(value) {
for (name, value) in
bevy_reflect::structs::Struct::iter_fields(struct_value) {
if let ::core::option::Option::Some(v) =
bevy_reflect::structs::Struct::field_mut(self, name) {
bevy_reflect::PartialReflect::try_apply(v, value)?;
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
to_kind: bevy_reflect::ReflectKind::Struct,
});
}
::core::result::Result::Ok(())
}
#[inline]
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::Struct
}
#[inline]
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::Struct(self)
}
#[inline]
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::Struct(self)
}
#[inline]
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::Struct(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
let value =
<dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
if let ::core::option::Option::Some(value) = value {
::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
value))
} else { ::core::option::Option::Some(false) }
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::structs::struct_partial_cmp)(self, value)
}
#[inline]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
}
}
impl bevy_reflect::FromReflect for TabList where {
fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
bevy_reflect::PartialReflect::reflect_ref(reflect) {
let mut __this =
<Self as ::core::default::Default>::default();
if let ::core::option::Option::Some(__field) =
(||
<ControlOrientation as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
"orientation")?))() {
__this.orientation = __field;
}
if let ::core::option::Option::Some(__field) =
(||
<TabActivation as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
"activation")?))() {
__this.activation = __field;
}
::core::option::Option::Some(__this)
} else { ::core::option::Option::None }
}
}
};Reflect)]
53#[require(AccessibilityNode(accesskit::Node::new(Role::TabList)), SelectedTab)]
54#[reflect(Component, Default, Clone, PartialEq)]
55pub struct TabList {
56 pub orientation: ControlOrientation,
58 pub activation: TabActivation,
60}
61
62impl Default for TabList {
63 fn default() -> Self {
64 Self {
65 orientation: ControlOrientation::Horizontal,
66 activation: TabActivation::default(),
67 }
68 }
69}
70
71#[derive(impl bevy_ecs::component::Component for SelectedTab where
Self: ::core::marker::Send + ::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component, impl bevy_ecs::template::FromTemplate for SelectedTab {
type Template = SelectedTabTemplate;
}
impl ::core::marker::Unpin for SelectedTab where
for<'a> [()]: bevy_ecs::template::SpecializeFromTemplate {}
#[allow(missing_docs)]
pub struct SelectedTabTemplate(pub <Option<Entity> as
bevy_ecs::template::BuiltInTemplate>::Template);
impl bevy_ecs::template::Template for SelectedTabTemplate {
type Output = SelectedTab;
fn build_template(&self,
context: &mut bevy_ecs::template::TemplateContext)
-> bevy_ecs::error::Result<Self::Output> {
bevy_ecs::error::Result::Ok(SelectedTab(self.0.build_template(context)?))
}
fn clone_template(&self) -> Self {
Self(bevy_ecs::template::Template::clone_template(&self.0))
}
}
impl ::core::default::Default for SelectedTabTemplate {
fn default() -> Self { Self(::core::default::Default::default()) }
}FromTemplate, #[automatically_derived]
impl ::core::fmt::Debug for SelectedTab {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "SelectedTab",
&&self.0)
}
}Debug, #[automatically_derived]
impl ::core::default::Default for SelectedTab {
#[inline]
fn default() -> Self { Self(::core::default::Default::default()) }
}Default, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for SelectedTab { }
#[automatically_derived]
impl ::core::cmp::PartialEq for SelectedTab {
#[inline]
fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SelectedTab {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Option<Entity>>;
}
}Eq, const _: () =
{
impl bevy_reflect::GetTypeRegistration for SelectedTab where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert(<bevy_reflect::ReflectFromPtr as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.insert(<bevy_reflect::ReflectFromReflect as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.register_type_data_with::<ReflectComponent, Self,
_>(());
registration.register_type_data_with::<ReflectDefault, Self,
_>(());
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {
<Option<Entity> as
bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
}
}
impl bevy_reflect::Typed for SelectedTab where {
#[inline(never)]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(#[inline(never)] ||
{
bevy_reflect::TypeInfo::TupleStruct(bevy_reflect::tuple_struct::TupleStructInfo::new::<Self>(&[bevy_reflect::UnnamedField::new::<Option<Entity>>(0usize)]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for SelectedTab where {
fn type_path() -> &'static str {
"bevy_ui_widgets::tabs::SelectedTab"
}
fn short_type_path() -> &'static str { "SelectedTab" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("SelectedTab")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_ui_widgets::tabs".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_ui_widgets::tabs")
}
}
impl bevy_reflect::Reflect for SelectedTab where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
#[allow(non_upper_case_globals)]
const _: () =
{
static __INVENTORY: ::inventory::Node =
::inventory::Node {
value: &{
bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<SelectedTab
as
bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
},
next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
};
#[link_section = ".text.startup"]
unsafe extern "C" fn __ctor() {
unsafe {
::inventory::ErasedNode::submit(__INVENTORY.value,
&__INVENTORY)
}
}
#[used]
#[link_section = ".init_array"]
static __CTOR: unsafe extern "C" fn() = __ctor;
};
impl bevy_reflect::tuple_struct::TupleStruct for SelectedTab where {
fn field(&self, index: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&self.0),
_ => ::core::option::Option::None,
}
}
fn field_mut(&mut self, index: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match index {
0usize => ::core::option::Option::Some(&mut self.0),
_ => ::core::option::Option::None,
}
}
#[inline]
fn field_len(&self) -> usize { 1usize }
#[inline]
fn iter_fields(&self)
-> bevy_reflect::tuple_struct::TupleStructFieldIter {
bevy_reflect::tuple_struct::TupleStructFieldIter::new(self)
}
fn to_dynamic_tuple_struct(&self)
->
::core::result::Result<bevy_reflect::tuple_struct::DynamicTupleStruct,
bevy_reflect::ReflectCloneError> {
let mut dynamic:
bevy_reflect::tuple_struct::DynamicTupleStruct =
::core::default::Default::default();
dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
dynamic.insert_boxed(bevy_reflect::PartialReflect::to_dynamic(&self.0)?);
::core::result::Result::Ok(dynamic)
}
}
impl bevy_reflect::PartialReflect for SelectedTab where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::TupleStruct(struct_value) =
bevy_reflect::PartialReflect::reflect_ref(value) {
for (i, value) in
::core::iter::Iterator::enumerate(bevy_reflect::tuple_struct::TupleStruct::iter_fields(struct_value))
{
if let ::core::option::Option::Some(v) =
bevy_reflect::tuple_struct::TupleStruct::field_mut(self, i)
{
bevy_reflect::PartialReflect::try_apply(v, value)?;
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
to_kind: bevy_reflect::ReflectKind::TupleStruct,
});
}
::core::result::Result::Ok(())
}
#[inline]
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::TupleStruct
}
#[inline]
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::TupleStruct(self)
}
#[inline]
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::TupleStruct(self)
}
#[inline]
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::TupleStruct(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
let value =
<dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
if let ::core::option::Option::Some(value) = value {
::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
value))
} else { ::core::option::Option::Some(false) }
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::tuple_struct::tuple_struct_partial_cmp)(self,
value)
}
#[inline]
#[allow(unreachable_code, reason =
"Ignored fields without a `clone` attribute will early-return with an error")]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(Self {
0: <Option<Entity> as
bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.0)?,
}))
}
}
impl bevy_reflect::FromReflect for SelectedTab where {
fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::TupleStruct(__ref_struct) =
bevy_reflect::PartialReflect::reflect_ref(reflect) {
let mut __this =
<Self as ::core::default::Default>::default();
if let ::core::option::Option::Some(__field) =
(||
<Option<Entity> as
bevy_reflect::FromReflect>::from_reflect(bevy_reflect::tuple_struct::TupleStruct::field(__ref_struct,
0)?))() {
__this.0 = __field;
}
::core::option::Option::Some(__this)
} else { ::core::option::Option::None }
}
}
};Reflect)]
76#[reflect(Component, Default, PartialEq)]
77pub struct SelectedTab(#[template(built_in)] pub Option<Entity>);
78
79#[derive(#[doc =
"**Required Components**: [`AccessibilityNode`], [`Selectable`], [`TabIndex`]. \n\n A component's Required Components are inserted whenever it is inserted. Note that this will also insert the required components _of_ the required components, recursively, in depth-first order."]
impl bevy_ecs::component::Component for Tab where Self: ::core::marker::Send +
::core::marker::Sync + 'static {
const STORAGE_TYPE: bevy_ecs::component::StorageType =
bevy_ecs::component::StorageType::Table;
type Mutability = bevy_ecs::component::Mutable;
fn register_required_components(_requiree:
bevy_ecs::component::ComponentId,
required_components:
&mut bevy_ecs::component::RequiredComponentsRegistrator) {
required_components.register_required::<AccessibilityNode>(||
{
let x: AccessibilityNode =
(||
AccessibilityNode(accesskit::Node::new(Role::Tab)))().into();
x
});
required_components.register_required::<Selectable>(<Selectable as
::core::default::Default>::default);
required_components.register_required::<TabIndex>(||
{ let x: TabIndex = (|| TabIndex(-1))().into(); x });
}
fn clone_behavior() -> bevy_ecs::component::ComponentCloneBehavior {
use bevy_ecs::component::{
DefaultCloneBehaviorBase, DefaultCloneBehaviorViaClone,
};
(&&&bevy_ecs::component::DefaultCloneBehaviorSpecialization::<Self>::default()).default_clone_behavior()
}
fn relationship_accessor()
->
::core::option::Option<bevy_ecs::relationship::ComponentRelationshipAccessor<Self>> {
::core::option::Option::None
}
}Component, #[automatically_derived]
impl ::core::fmt::Debug for Tab {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Tab")
}
}Debug, #[automatically_derived]
impl ::core::default::Default for Tab {
#[inline]
fn default() -> Self { Self }
}Default, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Tab { }
#[automatically_derived]
impl ::core::clone::Clone for Tab {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Tab { }Copy, const _: () =
{
impl bevy_reflect::GetTypeRegistration for Tab where {
fn get_type_registration() -> bevy_reflect::TypeRegistration {
let mut registration =
bevy_reflect::TypeRegistration::of::<Self>();
registration.insert(<bevy_reflect::ReflectFromPtr as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.insert(<bevy_reflect::ReflectFromReflect as
bevy_reflect::CreateTypeData<Self>>::create_type_data(()));
registration.register_type_data_with::<ReflectComponent, Self,
_>(());
registration.register_type_data_with::<ReflectDefault, Self,
_>(());
registration
}
#[inline(never)]
fn register_type_dependencies(registry:
&mut bevy_reflect::TypeRegistry) {}
}
impl bevy_reflect::Typed for Tab where {
#[inline(never)]
fn type_info() -> &'static bevy_reflect::TypeInfo {
static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
bevy_reflect::utility::NonGenericTypeInfoCell::new();
CELL.get_or_set(#[inline(never)] ||
{
bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[]))
})
}
}
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for Tab where {
fn type_path() -> &'static str { "bevy_ui_widgets::tabs::Tab" }
fn short_type_path() -> &'static str { "Tab" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("Tab")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_ui_widgets::tabs".split(':').next().unwrap())
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_ui_widgets::tabs")
}
}
impl bevy_reflect::Reflect for Tab where {
#[inline]
fn into_any(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any { self }
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
#[inline]
fn into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
self
}
#[inline]
fn set(&mut self,
value:
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
->
::core::result::Result<(),
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
::core::result::Result::Ok(())
}
}
#[allow(non_upper_case_globals)]
const _: () =
{
static __INVENTORY: ::inventory::Node =
::inventory::Node {
value: &{
bevy_reflect::__macro_exports::auto_register::AutomaticReflectRegistrations(<Tab
as
bevy_reflect::__macro_exports::auto_register::RegisterForReflection>::__register)
},
next: ::inventory::__private::UnsafeCell::new(::inventory::__private::Option::None),
};
#[link_section = ".text.startup"]
unsafe extern "C" fn __ctor() {
unsafe {
::inventory::ErasedNode::submit(__INVENTORY.value,
&__INVENTORY)
}
}
#[used]
#[link_section = ".init_array"]
static __CTOR: unsafe extern "C" fn() = __ctor;
};
impl bevy_reflect::structs::Struct for Tab where {
fn field(&self, name: &str)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match name { _ => ::core::option::Option::None, }
}
fn field_mut(&mut self, name: &str)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match name { _ => ::core::option::Option::None, }
}
fn field_at(&self, index: usize)
-> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
match index { _ => ::core::option::Option::None, }
}
fn field_at_mut(&mut self, index: usize)
->
::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
match index { _ => ::core::option::Option::None, }
}
fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
match index { _ => ::core::option::Option::None, }
}
fn index_of_name(&self, name: &str)
-> ::core::option::Option<usize> {
match name { _ => ::core::option::Option::None, }
}
fn field_len(&self) -> usize { 0usize }
fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
bevy_reflect::structs::FieldIter::new(self)
}
fn to_dynamic_struct(&self)
->
::core::result::Result<bevy_reflect::structs::DynamicStruct,
bevy_reflect::ReflectCloneError> {
let mut dynamic: bevy_reflect::structs::DynamicStruct =
::core::default::Default::default();
dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
::core::result::Result::Ok(dynamic)
}
}
impl bevy_reflect::PartialReflect for Tab where {
#[inline]
fn get_represented_type_info(&self)
-> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
::core::option::Option::Some(<Self as
bevy_reflect::Typed>::type_info())
}
#[inline]
fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
-> ::core::result::Result<(), bevy_reflect::ApplyError> {
if let bevy_reflect::ReflectRef::Struct(struct_value) =
bevy_reflect::PartialReflect::reflect_ref(value) {
for (name, value) in
bevy_reflect::structs::Struct::iter_fields(struct_value) {
if let ::core::option::Option::Some(v) =
bevy_reflect::structs::Struct::field_mut(self, name) {
bevy_reflect::PartialReflect::try_apply(v, value)?;
}
}
} else {
return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
to_kind: bevy_reflect::ReflectKind::Struct,
});
}
::core::result::Result::Ok(())
}
#[inline]
fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
bevy_reflect::ReflectKind::Struct
}
#[inline]
fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
bevy_reflect::ReflectRef::Struct(self)
}
#[inline]
fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
bevy_reflect::ReflectMut::Struct(self)
}
#[inline]
fn reflect_owned(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
-> bevy_reflect::ReflectOwned {
bevy_reflect::ReflectOwned::Struct(self)
}
#[inline]
fn try_into_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
::core::result::Result::Ok(self)
}
#[inline]
fn try_as_reflect(&self)
-> ::core::option::Option<&dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self)
-> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
::core::option::Option::Some(self)
}
#[inline]
fn into_partial_reflect(self:
bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
->
bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self)
-> &dyn bevy_reflect::PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self)
-> &mut dyn bevy_reflect::PartialReflect {
self
}
fn reflect_partial_eq(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<bool> {
(bevy_reflect::structs::struct_partial_eq)(self, value)
}
fn reflect_partial_cmp(&self,
value: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<::core::cmp::Ordering> {
(bevy_reflect::structs::struct_partial_cmp)(self, value)
}
#[inline]
fn reflect_clone(&self)
->
::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
bevy_reflect::ReflectCloneError> {
::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
}
}
impl bevy_reflect::FromReflect for Tab where {
fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
-> ::core::option::Option<Self> {
if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
bevy_reflect::PartialReflect::reflect_ref(reflect) {
let mut __this =
<Self as ::core::default::Default>::default();
::core::option::Option::Some(__this)
} else { ::core::option::Option::None }
}
}
};Reflect)]
84#[require(
85 AccessibilityNode(accesskit::Node::new(Role::Tab)),
86 Selectable,
87 TabIndex(-1)
88)]
89#[reflect(Component, Default, Clone)]
90pub struct Tab;
91
92pub struct TabPlugin;
94
95impl Plugin for TabPlugin {
96 fn build(&self, app: &mut App) {
97 app.add_observer(tablist_on_click)
98 .add_observer(tab_on_key_input)
99 .add_systems(
100 PostUpdate,
101 update_tablist_derived_state
102 .after(crate::MenuFocusSystem)
103 .before(InputFocusSystems::FocusChangeEvents),
104 );
105 }
106}
107
108pub fn tablist_self_update(
110 change: On<crate::ValueChange<Option<Entity>>>,
111 tablists: Query<(), With<TabList>>,
112 mut commands: Commands,
113) {
114 if tablists.contains(change.source) {
115 commands
116 .entity(change.source)
117 .insert(SelectedTab(change.value));
118 }
119}
120
121fn tablist_on_click(
122 mut click: On<PointerClick>,
123 tablists: Query<(&SelectedTab, Has<InteractionDisabled>), With<TabList>>,
124 tabs: Query<Has<InteractionDisabled>, With<Tab>>,
125 parents: Query<&ChildOf>,
126 mut commands: Commands,
127) {
128 if click.button != PointerButton::Primary {
129 return;
130 }
131 let Ok((selection, list_disabled)) = tablists.get(click.entity) else {
132 return;
133 };
134
135 let target = click.original_event_target();
136 let tab = if tabs.contains(target) {
137 Some(target)
138 } else {
139 parents
140 .iter_ancestors(target)
141 .take_while(|ancestor| *ancestor != click.entity)
142 .find(|ancestor| tabs.contains(*ancestor))
143 };
144 let Some(tab) = tab else {
145 return;
146 };
147 let Ok(parent) = parents.get(tab) else {
148 return;
149 };
150 if parent.parent() != click.entity {
151 return;
152 }
153 if list_disabled || tabs.get(tab).is_ok_and(|disabled| disabled) {
154 return;
155 }
156
157 click.propagate(false);
158 if selection.0 != Some(tab) {
159 commands.trigger(crate::ValueChange::<Option<Entity>> {
160 source: click.entity,
161 value: Some(tab),
162 is_final: true,
163 });
164 }
165}
166
167fn tab_on_key_input(
168 mut input: On<FocusedInput<KeyboardInput>>,
169 tablists: Query<(&TabList, &SelectedTab, &Children, Has<InteractionDisabled>)>,
170 tabs: Query<Has<InteractionDisabled>, With<Tab>>,
171 parents: Query<&ChildOf>,
172 mut focus: ResMut<InputFocus>,
173 mut focus_visible: ResMut<InputFocusVisible>,
174 mut commands: Commands,
175) {
176 if !tabs.contains(input.focused_entity) {
177 return;
178 }
179 let Ok(parent) = parents.get(input.focused_entity) else {
180 return;
181 };
182 let Ok((tablist, selection, children, list_disabled)) = tablists.get(parent.parent()) else {
183 return;
184 };
185 if list_disabled {
186 return;
187 }
188 let event = &input.input;
189 if event.state != ButtonState::Pressed || event.repeat {
190 return;
191 }
192
193 enum Navigation {
194 Previous,
195 Next,
196 First,
197 Last,
198 Activate,
199 }
200
201 let navigation = match event.key_code {
202 KeyCode::ArrowLeft if tablist.orientation == ControlOrientation::Horizontal => {
203 Navigation::Previous
204 }
205 KeyCode::ArrowRight if tablist.orientation == ControlOrientation::Horizontal => {
206 Navigation::Next
207 }
208 KeyCode::ArrowUp if tablist.orientation == ControlOrientation::Vertical => {
209 Navigation::Previous
210 }
211 KeyCode::ArrowDown if tablist.orientation == ControlOrientation::Vertical => {
212 Navigation::Next
213 }
214 KeyCode::Home => Navigation::First,
215 KeyCode::End => Navigation::Last,
216 KeyCode::Enter | KeyCode::Space => Navigation::Activate,
217 _ => return,
218 };
219
220 if #[allow(non_exhaustive_omitted_patterns)] match navigation {
Navigation::Activate => true,
_ => false,
}matches!(navigation, Navigation::Activate) {
221 if tabs
222 .get(input.focused_entity)
223 .is_ok_and(|disabled| disabled)
224 {
225 return;
226 }
227 input.propagate(false);
228 if selection.0 != Some(input.focused_entity) {
229 commands.trigger(crate::ValueChange::<Option<Entity>> {
230 source: parent.parent(),
231 value: Some(input.focused_entity),
232 is_final: true,
233 });
234 }
235 return;
236 }
237 input.propagate(false);
238
239 let enabled = children
240 .iter()
241 .copied()
242 .filter(|child| tabs.get(*child).is_ok_and(|disabled| !disabled))
243 .collect::<Vec<_>>();
244 if enabled.is_empty() {
245 return;
246 }
247
248 let current = enabled
249 .iter()
250 .position(|tab| *tab == input.focused_entity)
251 .or_else(|| {
252 selection
253 .0
254 .and_then(|selected| enabled.iter().position(|tab| *tab == selected))
255 });
256 let next_index = match navigation {
257 Navigation::Previous => current
258 .filter(|index| *index > 0)
259 .map_or(enabled.len() - 1, |index| index - 1),
260 Navigation::Next => current.map_or(0, |index| (index + 1) % enabled.len()),
261 Navigation::First => 0,
262 Navigation::Last => enabled.len() - 1,
263 Navigation::Activate => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
264 };
265 let next = enabled[next_index];
266 if focus.get() != Some(next) {
267 focus.set(next, FocusCause::Navigated);
268 }
269 focus_visible.0 = true;
270 if tablist.activation == TabActivation::Automatic && selection.0 != Some(next) {
271 commands.trigger(crate::ValueChange::<Option<Entity>> {
272 source: parent.parent(),
273 value: Some(next),
274 is_final: true,
275 });
276 }
277}
278
279fn update_tablist_derived_state(
290 tablists: Query<(&SelectedTab, &Children), With<TabList>>,
291 tabs: Query<(Has<InteractionDisabled>, Has<Selected>, &TabIndex), With<Tab>>,
292 focus: Option<Res<InputFocus>>,
293 changed_tablists: Query<(), (With<TabList>, Or<(Changed<SelectedTab>, Changed<Children>)>)>,
294 changed_tabs: Query<(), (With<Tab>, Or<(Added<Tab>, Added<InteractionDisabled>)>)>,
295 mut removed_disabled: RemovedComponents<InteractionDisabled>,
296 mut commands: Commands,
297) {
298 let focus_changed = focus.as_ref().is_some_and(DetectChanges::is_changed);
299 let disabled_removed = !removed_disabled.is_empty();
300 removed_disabled.clear();
301 if !focus_changed && !disabled_removed && changed_tablists.is_empty() && changed_tabs.is_empty()
302 {
303 return;
304 }
305
306 for (selection, children) in tablists.iter() {
307 let selected = selection.0.filter(|entity| {
308 children.contains(entity) && tabs.get(*entity).is_ok_and(|(disabled, _, _)| !disabled)
309 });
310 let focused = focus
311 .as_ref()
312 .and_then(|focus| focus.get())
313 .filter(|entity| {
314 children.contains(entity)
315 && tabs.get(*entity).is_ok_and(|(disabled, _, _)| !disabled)
316 });
317 let roving = focused.or(selected).or_else(|| {
318 children
319 .iter()
320 .find(|child| tabs.get(**child).is_ok_and(|(disabled, _, _)| !disabled))
321 .copied()
322 });
323
324 for child in children.iter() {
325 let Ok((_, is_selected, tab_index)) = tabs.get(*child) else {
326 continue;
327 };
328 let should_select = selected == Some(*child);
329 if should_select && !is_selected {
330 commands.entity(*child).insert(Selected);
331 } else if !should_select && is_selected {
332 commands.entity(*child).remove::<Selected>();
333 }
334
335 let desired_index = if roving == Some(*child) { 0 } else { -1 };
336 if tab_index.0 != desired_index {
337 commands.entity(*child).insert(TabIndex(desired_index));
338 }
339 }
340 }
341}
342
343#[cfg(test)]
344mod tests {
345 use super::*;
346 use bevy_ecs::{hierarchy::ChildOf, observer::On, resource::Resource, system::ResMut};
347 use bevy_input::{keyboard::Key, InputPlugin};
348 use bevy_input_focus::{FocusCause, InputDispatchPlugin, InputFocusPlugin};
349 use bevy_math::Vec2;
350 use bevy_picking::{
351 backend::HitData,
352 events::Pointer,
353 pointer::{Location, PointerButton, PointerId},
354 };
355 use bevy_window::{PrimaryWindow, Window, WindowRef};
356
357 #[derive(Resource, Default)]
358 struct SelectionRequests(Vec<(Entity, Option<Entity>)>);
359
360 fn tab_app() -> (App, Entity) {
361 let mut app = App::new();
362 app.add_plugins((
363 InputPlugin,
364 InputFocusPlugin,
365 InputDispatchPlugin,
366 TabPlugin,
367 ))
368 .init_resource::<SelectionRequests>()
369 .add_observer(
370 |change: On<crate::ValueChange<Option<Entity>>>,
371 mut requests: ResMut<SelectionRequests>| {
372 requests.0.push((change.source, change.value));
373 },
374 );
375 let window = app
376 .world_mut()
377 .spawn((Window::default(), PrimaryWindow))
378 .id();
379 app.update();
380 (app, window)
381 }
382
383 fn press_key(app: &mut App, key_code: KeyCode, window: Entity) {
384 let logical_key = match key_code {
385 KeyCode::ArrowLeft => Key::ArrowLeft,
386 KeyCode::ArrowRight => Key::ArrowRight,
387 KeyCode::ArrowUp => Key::ArrowUp,
388 KeyCode::ArrowDown => Key::ArrowDown,
389 KeyCode::Home => Key::Home,
390 KeyCode::End => Key::End,
391 KeyCode::Enter => Key::Enter,
392 KeyCode::Space => Key::Space,
393 _ => Key::Unidentified(bevy_input::keyboard::NativeKey::Unidentified),
394 };
395 app.world_mut().write_message(KeyboardInput {
396 key_code,
397 logical_key,
398 state: ButtonState::Pressed,
399 text: None,
400 repeat: false,
401 window,
402 });
403 app.update();
404 }
405
406 fn click(app: &mut App, target: Entity, window: Entity) {
407 click_with_button(app, target, window, PointerButton::Primary);
408 }
409
410 fn click_with_button(app: &mut App, target: Entity, window: Entity, button: PointerButton) {
411 let location = Location {
412 target: bevy_camera::NormalizedRenderTarget::Window(
413 WindowRef::Entity(window).normalize(Some(window)).unwrap(),
414 ),
415 position: Vec2::ZERO,
416 };
417 app.world_mut().trigger(PointerClick {
418 entity: target,
419 pointer: Pointer::new(PointerId::Mouse, location),
420 button,
421 hit: HitData::new(window, 0.0, None, None),
422 duration: core::time::Duration::from_millis(10),
423 count: 1,
424 });
425 app.update();
426 }
427
428 #[test]
429 fn clicking_enabled_tab_requests_selection_without_mutating_controlled_state() {
430 let (mut app, window) = tab_app();
431 let list = app
432 .world_mut()
433 .spawn((TabList::default(), ChildOf(window)))
434 .id();
435 let first = app.world_mut().spawn((Tab, ChildOf(list))).id();
436 let second = app.world_mut().spawn((Tab, ChildOf(list))).id();
437 app.world_mut()
438 .entity_mut(list)
439 .insert(SelectedTab(Some(first)));
440 app.update();
441
442 click(&mut app, second, window);
443
444 assert_eq!(
445 app.world().resource::<SelectionRequests>().0,
446 [(list, Some(second))]
447 );
448 assert_eq!(
449 app.world().entity(list).get::<SelectedTab>(),
450 Some(&SelectedTab(Some(first)))
451 );
452 }
453
454 #[test]
455 fn self_update_observer_applies_selection_request() {
456 let (mut app, window) = tab_app();
457 let list = app
458 .world_mut()
459 .spawn((TabList::default(), ChildOf(window)))
460 .observe(tablist_self_update)
461 .id();
462 let tab = app.world_mut().spawn((Tab, ChildOf(list))).id();
463 app.update();
464
465 click(&mut app, tab, window);
466
467 assert_eq!(
468 app.world().entity(list).get::<SelectedTab>(),
469 Some(&SelectedTab(Some(tab)))
470 );
471 }
472
473 #[test]
474 fn valid_selection_derives_selected_state_and_roving_entry() {
475 let (mut app, window) = tab_app();
476 let list = app
477 .world_mut()
478 .spawn((TabList::default(), ChildOf(window)))
479 .id();
480 let first = app.world_mut().spawn((Tab, ChildOf(list))).id();
481 let second = app.world_mut().spawn((Tab, ChildOf(list))).id();
482 app.world_mut()
483 .entity_mut(list)
484 .insert(SelectedTab(Some(second)));
485
486 app.update();
487
488 assert!(!app.world().entity(first).contains::<Selected>());
489 assert!(app.world().entity(second).contains::<Selected>());
490 assert_eq!(
491 app.world().entity(first).get::<TabIndex>(),
492 Some(&TabIndex(-1))
493 );
494 assert_eq!(
495 app.world().entity(second).get::<TabIndex>(),
496 Some(&TabIndex(0))
497 );
498 }
499
500 #[test]
501 fn invalid_selection_clears_selected_state_and_uses_first_enabled_roving_entry() {
502 let (mut app, window) = tab_app();
503 let stale = app.world_mut().spawn_empty().id();
504 let list = app
505 .world_mut()
506 .spawn((
507 TabList::default(),
508 SelectedTab(Some(stale)),
509 ChildOf(window),
510 ))
511 .id();
512 let disabled = app
513 .world_mut()
514 .spawn((Tab, Selected, InteractionDisabled, ChildOf(list)))
515 .id();
516 let enabled = app.world_mut().spawn((Tab, ChildOf(list))).id();
517
518 app.update();
519
520 assert!(!app.world().entity(disabled).contains::<Selected>());
521 assert!(!app.world().entity(enabled).contains::<Selected>());
522 assert_eq!(
523 app.world().entity(disabled).get::<TabIndex>(),
524 Some(&TabIndex(-1))
525 );
526 assert_eq!(
527 app.world().entity(enabled).get::<TabIndex>(),
528 Some(&TabIndex(0))
529 );
530 }
531
532 #[test]
533 fn horizontal_manual_arrow_navigation_wraps_and_skips_disabled_tabs() {
534 use bevy_input::keyboard::KeyCode;
535
536 let (mut app, window) = tab_app();
537 let list = app
538 .world_mut()
539 .spawn((TabList::default(), ChildOf(window)))
540 .id();
541 let first = app.world_mut().spawn((Tab, ChildOf(list))).id();
542 app.world_mut()
543 .spawn((Tab, InteractionDisabled, ChildOf(list)));
544 let last = app.world_mut().spawn((Tab, ChildOf(list))).id();
545 app.world_mut()
546 .entity_mut(list)
547 .insert(SelectedTab(Some(first)));
548 app.world_mut()
549 .resource_mut::<InputFocus>()
550 .set(first, FocusCause::Navigated);
551 app.update();
552
553 press_key(&mut app, KeyCode::ArrowRight, window);
554 assert_eq!(app.world().resource::<InputFocus>().get(), Some(last));
555
556 press_key(&mut app, KeyCode::ArrowRight, window);
557 assert_eq!(app.world().resource::<InputFocus>().get(), Some(first));
558
559 press_key(&mut app, KeyCode::ArrowLeft, window);
560 assert_eq!(app.world().resource::<InputFocus>().get(), Some(last));
561 assert!(
562 app.world().resource::<SelectionRequests>().0.is_empty(),
563 "manual navigation must not request selection"
564 );
565 }
566
567 #[test]
568 fn automatic_navigation_requests_selection_when_focus_moves() {
569 let (mut app, window) = tab_app();
570 let list = app
571 .world_mut()
572 .spawn((
573 TabList {
574 activation: TabActivation::Automatic,
575 ..Default::default()
576 },
577 ChildOf(window),
578 ))
579 .id();
580 let first = app.world_mut().spawn((Tab, ChildOf(list))).id();
581 let second = app.world_mut().spawn((Tab, ChildOf(list))).id();
582 app.world_mut()
583 .entity_mut(list)
584 .insert(SelectedTab(Some(first)));
585 app.world_mut()
586 .resource_mut::<InputFocus>()
587 .set(first, FocusCause::Navigated);
588 app.update();
589
590 press_key(&mut app, KeyCode::ArrowRight, window);
591
592 assert_eq!(app.world().resource::<InputFocus>().get(), Some(second));
593 assert_eq!(
594 app.world().resource::<SelectionRequests>().0,
595 [(list, Some(second))]
596 );
597 assert_eq!(
598 app.world().entity(list).get::<SelectedTab>(),
599 Some(&SelectedTab(Some(first))),
600 "automatic activation remains a controlled selection request"
601 );
602 }
603
604 #[test]
605 fn manual_tabs_request_selection_on_enter_and_space() {
606 let (mut app, window) = tab_app();
607 let list = app
608 .world_mut()
609 .spawn((TabList::default(), ChildOf(window)))
610 .id();
611 let tab = app.world_mut().spawn((Tab, ChildOf(list))).id();
612 app.world_mut()
613 .resource_mut::<InputFocus>()
614 .set(tab, FocusCause::Navigated);
615 app.update();
616
617 press_key(&mut app, KeyCode::Enter, window);
618 press_key(&mut app, KeyCode::Space, window);
619
620 assert_eq!(
621 app.world().resource::<SelectionRequests>().0,
622 [(list, Some(tab)), (list, Some(tab))]
623 );
624 }
625
626 #[test]
627 fn vertical_tabs_use_up_and_down_arrows_only() {
628 let (mut app, window) = tab_app();
629 let list = app
630 .world_mut()
631 .spawn((
632 TabList {
633 orientation: ControlOrientation::Vertical,
634 ..Default::default()
635 },
636 ChildOf(window),
637 ))
638 .id();
639 let first = app.world_mut().spawn((Tab, ChildOf(list))).id();
640 let second = app.world_mut().spawn((Tab, ChildOf(list))).id();
641 app.world_mut()
642 .resource_mut::<InputFocus>()
643 .set(first, FocusCause::Navigated);
644 app.update();
645
646 press_key(&mut app, KeyCode::ArrowRight, window);
647 assert_eq!(app.world().resource::<InputFocus>().get(), Some(first));
648
649 press_key(&mut app, KeyCode::ArrowDown, window);
650 assert_eq!(app.world().resource::<InputFocus>().get(), Some(second));
651
652 press_key(&mut app, KeyCode::ArrowUp, window);
653 assert_eq!(app.world().resource::<InputFocus>().get(), Some(first));
654 }
655
656 #[test]
657 fn home_and_end_focus_first_and_last_enabled_tabs() {
658 let (mut app, window) = tab_app();
659 let list = app
660 .world_mut()
661 .spawn((TabList::default(), ChildOf(window)))
662 .id();
663 app.world_mut()
664 .spawn((Tab, InteractionDisabled, ChildOf(list)));
665 let first_enabled = app.world_mut().spawn((Tab, ChildOf(list))).id();
666 let last_enabled = app.world_mut().spawn((Tab, ChildOf(list))).id();
667 app.world_mut()
668 .spawn((Tab, InteractionDisabled, ChildOf(list)));
669 app.world_mut()
670 .resource_mut::<InputFocus>()
671 .set(first_enabled, FocusCause::Navigated);
672 app.update();
673
674 press_key(&mut app, KeyCode::End, window);
675 assert_eq!(
676 app.world().resource::<InputFocus>().get(),
677 Some(last_enabled)
678 );
679
680 press_key(&mut app, KeyCode::Home, window);
681 assert_eq!(
682 app.world().resource::<InputFocus>().get(),
683 Some(first_enabled)
684 );
685 }
686
687 #[test]
688 fn focused_tab_is_the_roving_entry_during_manual_navigation() {
689 let (mut app, window) = tab_app();
690 let list = app
691 .world_mut()
692 .spawn((TabList::default(), ChildOf(window)))
693 .id();
694 let selected = app.world_mut().spawn((Tab, ChildOf(list))).id();
695 let focused = app.world_mut().spawn((Tab, ChildOf(list))).id();
696 app.world_mut()
697 .entity_mut(list)
698 .insert(SelectedTab(Some(selected)));
699 app.world_mut()
700 .resource_mut::<InputFocus>()
701 .set(focused, FocusCause::Navigated);
702
703 app.update();
704
705 assert_eq!(
706 app.world().entity(selected).get::<TabIndex>(),
707 Some(&TabIndex(-1))
708 );
709 assert_eq!(
710 app.world().entity(focused).get::<TabIndex>(),
711 Some(&TabIndex(0))
712 );
713 assert!(app.world().entity(selected).contains::<Selected>());
714 assert!(!app.world().entity(focused).contains::<Selected>());
715 }
716
717 #[test]
718 fn tablist_and_tab_install_accessibility_semantics() {
719 let (mut app, window) = tab_app();
720 let list = app
721 .world_mut()
722 .spawn((TabList::default(), ChildOf(window)))
723 .id();
724 let tab = app.world_mut().spawn((Tab, ChildOf(list))).id();
725 app.update();
726
727 let list_node = app.world().entity(list).get::<AccessibilityNode>().unwrap();
728 let tab_node = app.world().entity(tab).get::<AccessibilityNode>().unwrap();
729 assert_eq!(list_node.role(), Role::TabList);
730 assert_eq!(tab_node.role(), Role::Tab);
731 assert!(app.world().entity(tab).contains::<Selectable>());
732 }
733
734 #[test]
735 fn disabled_tab_does_not_request_selection() {
736 let (mut app, window) = tab_app();
737 let list = app
738 .world_mut()
739 .spawn((TabList::default(), ChildOf(window)))
740 .id();
741 let disabled = app
742 .world_mut()
743 .spawn((Tab, InteractionDisabled, ChildOf(list)))
744 .id();
745 app.update();
746
747 click(&mut app, disabled, window);
748
749 assert!(app.world().resource::<SelectionRequests>().0.is_empty());
750 }
751
752 #[test]
753 fn secondary_click_does_not_change_selection() {
754 let (mut app, window) = tab_app();
755 let list = app
756 .world_mut()
757 .spawn((TabList::default(), ChildOf(window)))
758 .id();
759 let tab = app.world_mut().spawn((Tab, ChildOf(list))).id();
760 app.update();
761
762 click_with_button(&mut app, tab, window, PointerButton::Secondary);
763 click_with_button(&mut app, tab, window, PointerButton::Middle);
764
765 assert!(app.world().resource::<SelectionRequests>().0.is_empty());
766 }
767
768 #[test]
769 fn activating_the_selected_tab_does_not_reemit() {
770 let (mut app, window) = tab_app();
771 let list = app
772 .world_mut()
773 .spawn((TabList::default(), ChildOf(window)))
774 .observe(tablist_self_update)
775 .id();
776 let tab = app.world_mut().spawn((Tab, ChildOf(list))).id();
777 app.update();
778
779 click(&mut app, tab, window);
780 click(&mut app, tab, window);
781
782 assert_eq!(
783 app.world().resource::<SelectionRequests>().0,
784 [(list, Some(tab))]
785 );
786 assert_eq!(
787 app.world().entity(list).get::<SelectedTab>(),
788 Some(&SelectedTab(Some(tab)))
789 );
790 }
791
792 #[test]
793 fn disabled_tablist_ignores_clicks_and_keys() {
794 let (mut app, window) = tab_app();
795 let list = app
796 .world_mut()
797 .spawn((TabList::default(), InteractionDisabled, ChildOf(window)))
798 .id();
799 let first = app.world_mut().spawn((Tab, ChildOf(list))).id();
800 let second = app.world_mut().spawn((Tab, ChildOf(list))).id();
801 app.world_mut()
802 .resource_mut::<InputFocus>()
803 .set(first, FocusCause::Navigated);
804 app.update();
805
806 click(&mut app, second, window);
807 press_key(&mut app, KeyCode::ArrowRight, window);
808 press_key(&mut app, KeyCode::Enter, window);
809
810 assert!(app.world().resource::<SelectionRequests>().0.is_empty());
811 assert_eq!(app.world().resource::<InputFocus>().get(), Some(first));
812 }
813}