More use of the ItemRc

This commit is contained in:
Olivier Goffart 2020-11-24 13:26:24 +01:00
parent 124eec9960
commit 0c97b4f296
7 changed files with 68 additions and 85 deletions

View file

@ -102,8 +102,8 @@ public:
void set_focus_item(const ComponentRc &component_rc, uintptr_t item_index) void set_focus_item(const ComponentRc &component_rc, uintptr_t item_index)
{ {
cbindgen_private::sixtyfps_component_window_set_focus_item(&inner, &component_rc, cbindgen_private::ItemRc item_rc{component_rc, item_index};
item_index); cbindgen_private::sixtyfps_component_window_set_focus_item(&inner, &item_rc);
} }
template<typename Component, typename ItemTree> template<typename Component, typename ItemTree>
@ -191,6 +191,7 @@ inline InputEventResult process_input_event(const ComponentRc &component_rc, int
mouse_event.pos = { mouse_event.pos.x - offset.x, mouse_event.pos.y - offset.y }; mouse_event.pos = { mouse_event.pos.x - offset.x, mouse_event.pos.y - offset.y };
const auto &item_node = tree.ptr[item_index]; const auto &item_node = tree.ptr[item_index];
InputEventResult result = InputEventResult::EventIgnored; InputEventResult result = InputEventResult::EventIgnored;
cbindgen_private::ItemRc item_rc{component_rc, uintptr_t(item_index)};
switch (item_node.tag) { switch (item_node.tag) {
case ItemTreeNode::Tag::Item: case ItemTreeNode::Tag::Item:
result = item_node.item.item.vtable->input_event( result = item_node.item.item.vtable->input_event(
@ -199,7 +200,7 @@ inline InputEventResult process_input_event(const ComponentRc &component_rc, int
reinterpret_cast<char *>(component_rc.borrow().instance) reinterpret_cast<char *>(component_rc.borrow().instance)
+ item_node.item.item.offset, + item_node.item.item.offset,
}, },
mouse_event, window, &component_rc, item_index); mouse_event, window, &item_rc);
break; break;
case ItemTreeNode::Tag::DynamicTree: { case ItemTreeNode::Tag::DynamicTree: {
ComponentRef comp = get_dynamic(item_node.dynamic_tree.index, rep_index); ComponentRef comp = get_dynamic(item_node.dynamic_tree.index, rep_index);

View file

@ -694,7 +694,7 @@ fn generate_component(
event.pos -= offset.to_vector(); event.pos -= offset.to_vector();
let res = match tree[item_index] { let res = match tree[item_index] {
ItemTreeNode::Item { item, .. } => { ItemTreeNode::Item { item, .. } => {
item.apply_pin(self).as_ref().input_event(event, window, &self_rc, item_index) item.apply_pin(self).as_ref().input_event(event, window, &ItemRc::new(self_rc, item_index))
} }
ItemTreeNode::DynamicTree { index } => { ItemTreeNode::DynamicTree { index } => {
match index { match index {
@ -1059,7 +1059,7 @@ fn compile_expression(e: &Expression, component: &Rc<Component>) -> TokenStream
let focus_item = focus_item.borrow(); let focus_item = focus_item.borrow();
let item_index = focus_item.item_index.get().unwrap(); let item_index = focus_item.item_index.get().unwrap();
quote!( quote!(
_self.window.set_focus_item(&VRc::into_dyn(_self.self_weak.get().unwrap().upgrade().unwrap()), #item_index); _self.window.set_focus_item(&ItemRc::new(VRc::into_dyn(_self.self_weak.get().unwrap().upgrade().unwrap()), #item_index));
) )
} else { } else {
panic!("internal error: argument to SetFocusItem must be an element") panic!("internal error: argument to SetFocusItem must be an element")

View file

@ -594,11 +594,10 @@ pub mod ffi {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sixtyfps_component_window_set_focus_item( pub unsafe extern "C" fn sixtyfps_component_window_set_focus_item(
handle: *const ComponentWindowOpaque, handle: *const ComponentWindowOpaque,
focus_item_component: &ComponentRc, focus_item: &ItemRc,
focus_item_index: usize,
) { ) {
let window = &*(handle as *const ComponentWindow); let window = &*(handle as *const ComponentWindow);
window.set_focus_item(&ItemRc::new(focus_item_component.clone(), focus_item_index)) window.set_focus_item(focus_item)
} }
/// Associates the window with the given component. /// Associates the window with the given component.

View file

@ -491,7 +491,11 @@ pub fn process_ungrabbed_mouse_event(
if geom.contains(event.pos) { if geom.contains(event.pos) {
let mut event2 = event.clone(); let mut event2 = event.clone();
event2.pos -= geom.origin.to_vector(); event2.pos -= geom.origin.to_vector();
match item.as_ref().input_event(event2, window, comp_rc, item_index) { match item.as_ref().input_event(
event2,
window,
&crate::items::ItemRc::new(comp_rc.clone(), item_index),
) {
InputEventResult::EventAccepted => { InputEventResult::EventAccepted => {
result = InputEventResult::EventAccepted; result = InputEventResult::EventAccepted;
return ItemVisitorResult::Abort; return ItemVisitorResult::Abort;

View file

@ -24,7 +24,6 @@ When adding an item or a property, it needs to be kept in sync with different pl
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
#![allow(missing_docs)] // because documenting each property of items is redundent #![allow(missing_docs)] // because documenting each property of items is redundent
use super::component::ComponentVTable;
use super::eventloop::ComponentWindow; use super::eventloop::ComponentWindow;
use super::graphics::{Color, HighLevelRenderingPrimitive, IntRect, PathData, Rect, Resource}; use super::graphics::{Color, HighLevelRenderingPrimitive, IntRect, PathData, Rect, Resource};
use super::input::{ use super::input::{
@ -33,6 +32,7 @@ use super::input::{
}; };
use super::item_rendering::CachedRenderingData; use super::item_rendering::CachedRenderingData;
use super::layout::LayoutInfo; use super::layout::LayoutInfo;
use crate::component::ComponentVTable;
use crate::font::HasFont; use crate::font::HasFont;
#[cfg(feature = "rtti")] #[cfg(feature = "rtti")]
use crate::rtti::*; use crate::rtti::*;
@ -84,8 +84,7 @@ pub struct ItemVTable {
core::pin::Pin<VRef<ItemVTable>>, core::pin::Pin<VRef<ItemVTable>>,
MouseEvent, MouseEvent,
window: &ComponentWindow, window: &ComponentWindow,
self_component: &VRc<ComponentVTable, vtable::Dyn>, self_rc: &ItemRc,
self_index: usize,
) -> InputEventResult, ) -> InputEventResult,
pub focus_event: pub focus_event:
@ -103,19 +102,20 @@ pub struct ItemVTable {
pub type ItemRef<'a> = vtable::VRef<'a, ItemVTable>; pub type ItemRef<'a> = vtable::VRef<'a, ItemVTable>;
/// A ItemRc is holding a reference to a component containing the item, and the index of this item /// A ItemRc is holding a reference to a component containing the item, and the index of this item
#[repr(C)]
pub struct ItemRc { pub struct ItemRc {
component: crate::component::ComponentRc, component: vtable::VRc<ComponentVTable>,
index: usize, index: usize,
} }
impl ItemRc { impl ItemRc {
/// Create an ItemRc from a component and an index /// Create an ItemRc from a component and an index
pub fn new(component: crate::component::ComponentRc, index: usize) -> Self { pub fn new(component: vtable::VRc<ComponentVTable>, index: usize) -> Self {
Self { component, index } Self { component, index }
} }
/// Return a `Pin<ItemRef<'a>>` /// Return a `Pin<ItemRef<'a>>`
pub fn borrow<'a>(&'a self) -> Pin<ItemRef<'a>> { pub fn borrow<'a>(&'a self) -> Pin<ItemRef<'a>> {
let comp_ref_pin = crate::component::ComponentRc::borrow_pin(&self.component); let comp_ref_pin = vtable::VRc::borrow_pin(&self.component);
let result = comp_ref_pin.as_ref().get_item_ref(self.index); let result = comp_ref_pin.as_ref().get_item_ref(self.index);
// Safety: we can expand the lifetime of the ItemRef because we know it lives for at least the // Safety: we can expand the lifetime of the ItemRef because we know it lives for at least the
// lifetime of the component, which is 'a. Pin::as_ref removes the lifetime, but we can just put it back. // lifetime of the component, which is 'a. Pin::as_ref removes the lifetime, but we can just put it back.
@ -198,8 +198,7 @@ impl Item for Rectangle {
self: Pin<&Self>, self: Pin<&Self>,
_: MouseEvent, _: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &VRc<ComponentVTable, vtable::Dyn>, _self_rc: &ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
InputEventResult::EventIgnored InputEventResult::EventIgnored
} }
@ -287,8 +286,7 @@ impl Item for BorderRectangle {
self: Pin<&Self>, self: Pin<&Self>,
_: MouseEvent, _: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &VRc<ComponentVTable, vtable::Dyn>, _self_rc: &ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
InputEventResult::EventIgnored InputEventResult::EventIgnored
} }
@ -375,8 +373,7 @@ impl Item for Image {
self: Pin<&Self>, self: Pin<&Self>,
_: MouseEvent, _: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &VRc<ComponentVTable, vtable::Dyn>, _self_rc: &ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
InputEventResult::EventIgnored InputEventResult::EventIgnored
} }
@ -472,8 +469,7 @@ impl Item for ClippedImage {
self: Pin<&Self>, self: Pin<&Self>,
_: MouseEvent, _: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &VRc<ComponentVTable, vtable::Dyn>, _self_rc: &ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
InputEventResult::EventIgnored InputEventResult::EventIgnored
} }
@ -612,8 +608,7 @@ impl Item for Text {
self: Pin<&Self>, self: Pin<&Self>,
_: MouseEvent, _: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &VRc<ComponentVTable, vtable::Dyn>, _self_rc: &ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
InputEventResult::EventIgnored InputEventResult::EventIgnored
} }
@ -719,8 +714,7 @@ impl Item for TouchArea {
self: Pin<&Self>, self: Pin<&Self>,
event: MouseEvent, event: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &VRc<ComponentVTable, vtable::Dyn>, _self_rc: &ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
Self::FIELD_OFFSETS.mouse_x.apply_pin(self).set(event.pos.x); Self::FIELD_OFFSETS.mouse_x.apply_pin(self).set(event.pos.x);
Self::FIELD_OFFSETS.mouse_y.apply_pin(self).set(event.pos.y); Self::FIELD_OFFSETS.mouse_y.apply_pin(self).set(event.pos.y);
@ -818,8 +812,7 @@ impl Item for Clip {
self: Pin<&Self>, self: Pin<&Self>,
_: MouseEvent, _: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &VRc<ComponentVTable, vtable::Dyn>, _self_rc: &ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
InputEventResult::EventIgnored InputEventResult::EventIgnored
} }
@ -899,8 +892,7 @@ impl Item for Path {
self: Pin<&Self>, self: Pin<&Self>,
_: MouseEvent, _: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &VRc<ComponentVTable, vtable::Dyn>, _self_rc: &ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
InputEventResult::EventIgnored InputEventResult::EventIgnored
} }
@ -976,8 +968,7 @@ impl Item for Flickable {
self: Pin<&Self>, self: Pin<&Self>,
event: MouseEvent, event: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &VRc<ComponentVTable, vtable::Dyn>, _self_rc: &ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
if !Self::FIELD_OFFSETS.interactive.apply_pin(self).get() { if !Self::FIELD_OFFSETS.interactive.apply_pin(self).get() {
return InputEventResult::EventIgnored; return InputEventResult::EventIgnored;
@ -1102,8 +1093,7 @@ impl Item for Window {
self: Pin<&Self>, self: Pin<&Self>,
_event: MouseEvent, _event: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &VRc<ComponentVTable, vtable::Dyn>, _self_rc: &ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
InputEventResult::EventIgnored InputEventResult::EventIgnored
} }
@ -1258,8 +1248,7 @@ impl Item for TextInput {
self: Pin<&Self>, self: Pin<&Self>,
event: MouseEvent, event: MouseEvent,
window: &ComponentWindow, window: &ComponentWindow,
self_component: &VRc<ComponentVTable, vtable::Dyn>, self_rc: &ItemRc,
self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
if !Self::FIELD_OFFSETS.enabled.apply_pin(self).get() { if !Self::FIELD_OFFSETS.enabled.apply_pin(self).get() {
return InputEventResult::EventIgnored; return InputEventResult::EventIgnored;
@ -1274,7 +1263,7 @@ impl Item for TextInput {
self.as_ref().anchor_position.set(clicked_offset); self.as_ref().anchor_position.set(clicked_offset);
self.as_ref().cursor_position.set(clicked_offset); self.as_ref().cursor_position.set(clicked_offset);
if !Self::FIELD_OFFSETS.has_focus.apply_pin(self).get() { if !Self::FIELD_OFFSETS.has_focus.apply_pin(self).get() {
window.set_focus_item(&ItemRc::new(self_component.clone(), self_index)); window.set_focus_item(self_rc);
} }
} }

View file

@ -1455,35 +1455,35 @@ extern "C" fn input_event(
let comp_rc = instance_ref.self_weak().get().unwrap().upgrade().unwrap(); let comp_rc = instance_ref.self_weak().get().unwrap().upgrade().unwrap();
let mouse_grabber = extra_data.mouse_grabber.get(); let mouse_grabber = extra_data.mouse_grabber.get();
let (status, new_grab) = let (status, new_grab) = if let Some((item_index, rep_index)) = mouse_grabber.aborted_indexes()
if let Some((item_index, rep_index)) = mouse_grabber.aborted_indexes() { {
let tree = &component_type.item_tree; let tree = &component_type.item_tree;
let offset = sixtyfps_corelib::item_tree::item_offset(instance, tree, item_index); let offset = sixtyfps_corelib::item_tree::item_offset(instance, tree, item_index);
let mut event = mouse_event.clone(); let mut event = mouse_event.clone();
event.pos -= offset.to_vector(); event.pos -= offset.to_vector();
let res = let res = match tree[item_index] {
match tree[item_index] { ItemTreeNode::Item { item, .. } => item.apply_pin(instance).as_ref().input_event(
ItemTreeNode::Item { item, .. } => item event,
.apply_pin(instance)
.as_ref()
.input_event(event, window, &vtable::VRc::into_dyn(comp_rc), item_index),
ItemTreeNode::DynamicTree { index } => {
generativity::make_guard!(guard);
let rep_in_comp = component_type.repeater[index].unerase(guard);
rep_in_comp.offset.apply_pin(instance).input_event(rep_index, event, window)
}
};
match res {
sixtyfps_corelib::input::InputEventResult::GrabMouse => (res, mouse_grabber),
_ => (res, VisitChildrenResult::CONTINUE),
}
} else {
sixtyfps_corelib::input::process_ungrabbed_mouse_event(
&vtable::VRc::into_dyn(comp_rc),
mouse_event,
window, window,
) &sixtyfps_corelib::items::ItemRc::new(vtable::VRc::into_dyn(comp_rc), item_index),
),
ItemTreeNode::DynamicTree { index } => {
generativity::make_guard!(guard);
let rep_in_comp = component_type.repeater[index].unerase(guard);
rep_in_comp.offset.apply_pin(instance).input_event(rep_index, event, window)
}
}; };
match res {
sixtyfps_corelib::input::InputEventResult::GrabMouse => (res, mouse_grabber),
_ => (res, VisitChildrenResult::CONTINUE),
}
} else {
sixtyfps_corelib::input::process_ungrabbed_mouse_event(
&vtable::VRc::into_dyn(comp_rc),
mouse_event,
window,
)
};
extra_data.mouse_grabber.set(new_grab); extra_data.mouse_grabber.set(new_grab);
status status
} }

View file

@ -27,14 +27,13 @@ it needs to be kept in sync with different place.
use const_field_offset::FieldOffsets; use const_field_offset::FieldOffsets;
use core::pin::Pin; use core::pin::Pin;
use cpp::cpp; use cpp::cpp;
use sixtyfps_corelib::component::ComponentVTable;
use sixtyfps_corelib::eventloop::ComponentWindow; use sixtyfps_corelib::eventloop::ComponentWindow;
use sixtyfps_corelib::graphics::{HighLevelRenderingPrimitive, Rect, RenderingVariable, Resource}; use sixtyfps_corelib::graphics::{HighLevelRenderingPrimitive, Rect, RenderingVariable, Resource};
use sixtyfps_corelib::input::{ use sixtyfps_corelib::input::{
FocusEvent, InputEventResult, KeyEvent, KeyEventResult, MouseEvent, MouseEventType, FocusEvent, InputEventResult, KeyEvent, KeyEventResult, MouseEvent, MouseEventType,
}; };
use sixtyfps_corelib::item_rendering::CachedRenderingData; use sixtyfps_corelib::item_rendering::CachedRenderingData;
use sixtyfps_corelib::items::{Item, ItemConsts, ItemVTable}; use sixtyfps_corelib::items::{Item, ItemConsts, ItemRc, ItemVTable};
use sixtyfps_corelib::layout::LayoutInfo; use sixtyfps_corelib::layout::LayoutInfo;
use sixtyfps_corelib::rtti::*; use sixtyfps_corelib::rtti::*;
use sixtyfps_corelib::{ItemVTable_static, Property, SharedArray, SharedString, Signal}; use sixtyfps_corelib::{ItemVTable_static, Property, SharedArray, SharedString, Signal};
@ -200,8 +199,7 @@ impl Item for NativeButton {
self: Pin<&Self>, self: Pin<&Self>,
event: MouseEvent, event: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>, _self_rc: &sixtyfps_corelib::items::ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get(); let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get();
if !enabled { if !enabled {
@ -336,8 +334,7 @@ impl Item for NativeCheckBox {
self: Pin<&Self>, self: Pin<&Self>,
event: MouseEvent, event: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>, _self_rc: &sixtyfps_corelib::items::ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
if matches!(event.what, MouseEventType::MouseReleased) { if matches!(event.what, MouseEventType::MouseReleased) {
Self::FIELD_OFFSETS Self::FIELD_OFFSETS
@ -501,8 +498,7 @@ impl Item for NativeSpinBox {
self: Pin<&Self>, self: Pin<&Self>,
event: MouseEvent, event: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>, _self_rc: &sixtyfps_corelib::items::ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
let size: qttypes::QSize = get_size!(self); let size: qttypes::QSize = get_size!(self);
let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get(); let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get();
@ -712,8 +708,7 @@ impl Item for NativeSlider {
self: Pin<&Self>, self: Pin<&Self>,
event: MouseEvent, event: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>, _self_rc: &sixtyfps_corelib::items::ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
let size: qttypes::QSize = get_size!(self); let size: qttypes::QSize = get_size!(self);
let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get(); let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get();
@ -974,8 +969,7 @@ impl Item for NativeGroupBox {
self: Pin<&Self>, self: Pin<&Self>,
_: MouseEvent, _: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>, _self_rc: &sixtyfps_corelib::items::ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
InputEventResult::EventIgnored InputEventResult::EventIgnored
} }
@ -1130,8 +1124,7 @@ impl Item for NativeLineEdit {
self: Pin<&Self>, self: Pin<&Self>,
_: MouseEvent, _: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>, _self_rc: &sixtyfps_corelib::items::ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
InputEventResult::EventIgnored InputEventResult::EventIgnored
} }
@ -1385,8 +1378,7 @@ impl Item for NativeScrollView {
self: Pin<&Self>, self: Pin<&Self>,
event: MouseEvent, event: MouseEvent,
window: &ComponentWindow, window: &ComponentWindow,
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>, _self_rc: &sixtyfps_corelib::items::ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
let dpr = window.scale_factor(); let dpr = window.scale_factor();
let size: qttypes::QSize = get_size!(self); let size: qttypes::QSize = get_size!(self);
@ -1654,8 +1646,7 @@ impl Item for NativeStandardListViewItem {
self: Pin<&Self>, self: Pin<&Self>,
_event: MouseEvent, _event: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>, _self_rc: &sixtyfps_corelib::items::ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
InputEventResult::EventIgnored InputEventResult::EventIgnored
} }
@ -1779,8 +1770,7 @@ impl Item for NativeComboBox {
self: Pin<&Self>, self: Pin<&Self>,
event: MouseEvent, event: MouseEvent,
_window: &ComponentWindow, _window: &ComponentWindow,
_self_component: &vtable::VRc<ComponentVTable, vtable::Dyn>, _self_rc: &sixtyfps_corelib::items::ItemRc,
_self_index: usize,
) -> InputEventResult { ) -> InputEventResult {
let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get(); let enabled = Self::FIELD_OFFSETS.enabled.apply_pin(self).get();
if !enabled { if !enabled {