Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added the focus tree as a resource for UI systems. #252

Merged
merged 3 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ jobs:
- name: Run fmt check
run: cargo fmt --all -- --check
- name: Run clippy
run: cargo clippy --workspace --all-targets --all-features --features "bevy/x11"
run: cargo clippy --workspace --all-targets --all-features --features "bevy/x11" -- --deny warnings
4 changes: 2 additions & 2 deletions examples/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ fn startup(
<ElementBundle
styles={KStyle {
position_type: StyleProp::Value(KPositionType::SelfDirected),
left: StyleProp::Value(Units::Pixels(-34.545261 * 7.6)),
top: StyleProp::Value(Units::Pixels(10.0 - 95.557219 * 7.6)),
left: StyleProp::Value(Units::Pixels(-34.545 * 7.6)),
top: StyleProp::Value(Units::Pixels(10.0 - 95.557 * 7.6)),
..Default::default()
}}
>
Expand Down
58 changes: 24 additions & 34 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ type WidgetSystems = HashMap<
pub struct KayakRootContext {
pub tree: Arc<RwLock<Tree>>,
pub(crate) layout_cache: Arc<RwLock<LayoutCache>>,
pub(crate) focus_tree: Arc<RwLock<FocusTree>>,
pub(crate) focus_tree: FocusTree,
systems: WidgetSystems,
pub(crate) current_z: f32,
pub(crate) context_entities: ContextEntities,
Expand Down Expand Up @@ -140,14 +140,6 @@ impl KayakRootContext {
plugin.build(self)
}

/// Retreives the current entity that has focus or None if nothing is focused.
pub fn get_current_focus(&self) -> Option<Entity> {
if let Ok(tree) = self.focus_tree.try_read() {
return tree.current().map(|a| a.0);
}
None
}

/// Get's the layout for th given widget index.
pub(crate) fn get_layout(&self, id: &WrappedIndex) -> Option<Rect> {
if let Ok(cache) = self.layout_cache.try_read() {
Expand Down Expand Up @@ -245,10 +237,10 @@ impl KayakRootContext {
/// widget_context.add_widget(None, root_entity);
/// }
///```
pub fn spawn_widget<'a>(
pub fn spawn_widget(
&self,
commands: &mut Commands,
key: Option<&'a str>,
key: Option<&str>,
parent_id: Option<Entity>,
) -> Entity {
let mut entity = None;
Expand Down Expand Up @@ -647,18 +639,16 @@ pub fn update_widgets_sys(world: &mut World) {

// let change_tick = world.increment_change_tick();

let old_focus = if let Ok(mut focus_tree) = context.focus_tree.try_write() {
let current = focus_tree.current();
focus_tree.clear();
if let Ok(tree) = context.tree.read() {
if let Some(root_node) = tree.root_node {
focus_tree.add(root_node, &tree);
}
}
current
} else {
None
};
// let old_focus = {
// let current = context.focus_tree.current();
// context.focus_tree.clear();
// if let Ok(tree) = context.tree.read() {
// if let Some(root_node) = tree.root_node {
// context.focus_tree.add(root_node, &tree);
// }
// }
// current
// };

let mut new_ticks = HashMap::new();

Expand All @@ -681,13 +671,11 @@ pub fn update_widgets_sys(world: &mut World) {
&context.unique_ids_parents,
);

if let Some(old_focus) = old_focus {
if let Ok(mut focus_tree) = context.focus_tree.try_write() {
if focus_tree.contains(old_focus) {
focus_tree.focus(old_focus);
}
}
}
// if let Some(old_focus) = old_focus {
// if context.focus_tree.contains(old_focus) {
// context.focus_tree.focus(old_focus);
// }
// }

let tick = world.read_change_tick();

Expand Down Expand Up @@ -718,7 +706,7 @@ fn update_widgets(
systems: &mut WidgetSystems,
widgets: Vec<WrappedIndex>,
context_entities: &ContextEntities,
focus_tree: &Arc<RwLock<FocusTree>>,
focus_tree: &FocusTree,
clone_systems: &Arc<RwLock<EntityCloneSystems>>,
cloned_widget_entities: &Arc<RwLock<HashMap<Entity, Entity>>>,
widget_state: &WidgetState,
Expand Down Expand Up @@ -754,6 +742,7 @@ fn update_widgets(
let (widget_context, should_update_children) = update_widget(
systems,
tree,
focus_tree,
world,
*entity,
widget_type.0.clone(),
Expand Down Expand Up @@ -1145,9 +1134,7 @@ fn update_widgets(
if let Some(entity_ref) = world.get_entity(entity.0) {
if entity_ref.contains::<Focusable>() {
if let Ok(tree) = tree.try_read() {
if let Ok(mut focus_tree) = focus_tree.try_write() {
focus_tree.add(*entity, &tree);
}
focus_tree.add(*entity, &tree);
}
}
}
Expand All @@ -1157,6 +1144,7 @@ fn update_widgets(
fn update_widget(
systems: &mut WidgetSystems,
tree: &Arc<RwLock<Tree>>,
focus_tree: &FocusTree,
world: &mut World,
entity: WrappedIndex,
widget_type: String,
Expand Down Expand Up @@ -1311,12 +1299,14 @@ fn update_widget(
let widget_render_system = &mut systems.get_mut(&widget_type).unwrap().1;
let old_tick = widget_render_system.get_last_change_tick();
world.insert_resource(widget_context.clone());
world.insert_resource(focus_tree.clone());
should_update_children = widget_render_system.run(entity.0, world);
let new_tick = widget_render_system.get_last_change_tick();
new_ticks.insert(widget_type.clone(), new_tick);
widget_render_system.set_last_change_tick(old_tick);
widget_render_system.apply_buffers(world);
world.remove_resource::<KayakWidgetContext>();
world.remove_resource::<FocusTree>();

if let Ok(mut indices) = widget_context.index.try_write() {
indices.insert(entity.0, 0);
Expand Down
134 changes: 65 additions & 69 deletions src/event_dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ impl EventDispatcher {
(event_dispatcher_context, node_event) = on_event.try_call(
event_dispatcher_context,
context.widget_state.clone(),
context.focus_tree.clone(),
index.0,
node_event,
world,
Expand Down Expand Up @@ -437,67 +438,67 @@ impl EventDispatcher {
}
}

if let Ok(mut focus_tree) = context.focus_tree.try_write() {
// === Keyboard Events === //
for input_event in input_events {
// Keyboard events only care about the currently focused widget so we don't need to run this over every node in the tree
let events =
self.process_keyboard_events(input_event, &mut states, &focus_tree);
event_stream.extend(events);
}
// === Keyboard Events === //
for input_event in input_events {
// Keyboard events only care about the currently focused widget so we don't need to run this over every node in the tree
let events =
self.process_keyboard_events(input_event, &mut states, &context.focus_tree);
event_stream.extend(events);
}

// === Additional Events === //
let mut had_focus_event = false;

// These events are ones that require a specific target and need the tree to be evaluated before selecting the best match
for (event_type, state) in states {
if let Some(node) = state.best_match {
event_stream.push(KEvent::new(node.0, event_type));

match event_type {
EventType::Focus => {
had_focus_event = true;
if let Some(current_focus) = focus_tree.current() {
if current_focus != node {
event_stream
.push(KEvent::new(current_focus.0, EventType::Blur));
}
// === Additional Events === //
let mut had_focus_event = false;

// These events are ones that require a specific target and need the tree to be evaluated before selecting the best match
for (event_type, state) in states {
if let Some(node) = state.best_match {
event_stream.push(KEvent::new(node.0, event_type));

match event_type {
EventType::Focus => {
had_focus_event = true;
if let Some(current_focus) =
context.focus_tree.current().map(WrappedIndex)
{
if current_focus != node {
event_stream
.push(KEvent::new(current_focus.0, EventType::Blur));
}
focus_tree.focus(node);
}
EventType::Hover(..) => {
self.hovered = Some(node);
}
_ => {}
context.focus_tree.focus(node.0);
}
EventType::Hover(..) => {
self.hovered = Some(node);
}
_ => {}
}
}
}

// --- Blur Event --- //
if !had_focus_event && input_events.contains(&InputEvent::MouseLeftPress) {
// A mouse press didn't contain a focus event -> blur
if let Some(current_focus) = focus_tree.current() {
event_stream.push(KEvent::new(current_focus.0, EventType::Blur));
focus_tree.blur();
}
// --- Blur Event --- //
if !had_focus_event && input_events.contains(&InputEvent::MouseLeftPress) {
// A mouse press didn't contain a focus event -> blur
if let Some(current_focus) = context.focus_tree.current() {
event_stream.push(KEvent::new(current_focus, EventType::Blur));
context.focus_tree.blur();
}
}

// === Process Cursor States === //
self.current_mouse_position = self.next_mouse_position;
self.is_mouse_pressed = self.next_mouse_pressed;
// === Process Cursor States === //
self.current_mouse_position = self.next_mouse_position;
self.is_mouse_pressed = self.next_mouse_pressed;

if self.hovered.is_none() {
// No change -> revert
self.hovered = old_hovered;
}
if self.contains_cursor.is_none() {
// No change -> revert
self.contains_cursor = old_contains_cursor;
}
if self.wants_cursor.is_none() {
// No change -> revert
self.wants_cursor = old_wants_cursor;
}
if self.hovered.is_none() {
// No change -> revert
self.hovered = old_hovered;
}
if self.contains_cursor.is_none() {
// No change -> revert
self.contains_cursor = old_contains_cursor;
}
if self.wants_cursor.is_none() {
// No change -> revert
self.wants_cursor = old_wants_cursor;
}
}

Expand Down Expand Up @@ -694,7 +695,7 @@ impl EventDispatcher {
if let Some(current_focus) = focus_tree.current() {
match input_event {
InputEvent::CharEvent { c } => {
event_stream.push(KEvent::new(current_focus.0, EventType::CharInput { c: *c }))
event_stream.push(KEvent::new(current_focus, EventType::CharInput { c: *c }))
}
InputEvent::Keyboard { key, is_pressed } => {
// === Modifers === //
Expand All @@ -717,12 +718,12 @@ impl EventDispatcher {
// === Event === //
if *is_pressed {
event_stream.push(KEvent::new(
current_focus.0,
current_focus,
EventType::KeyDown(KeyboardEvent::new(*key, self.keyboard_modifiers)),
))
} else {
event_stream.push(KEvent::new(
current_focus.0,
current_focus,
EventType::KeyUp(KeyboardEvent::new(*key, self.keyboard_modifiers)),
))
}
Expand Down Expand Up @@ -798,30 +799,25 @@ impl EventDispatcher {
) {
if let EventType::KeyDown(evt) = event.event_type {
if let KeyCode::Tab = evt.key() {
let (index, current_focus) =
if let Ok(mut focus_tree) = context.focus_tree.try_write() {
let current_focus = focus_tree.current();
let (index, current_focus) = {
let current_focus = context.focus_tree.current();

let index = if evt.is_shift_pressed() {
focus_tree.prev()
} else {
focus_tree.next()
};
(index, current_focus)
let index = if evt.is_shift_pressed() {
context.focus_tree.prev()
} else {
(None, None)
context.focus_tree.next()
};
(index, current_focus)
};

if let Some(index) = index {
let mut events = vec![KEvent::new(index.0, EventType::Focus)];
let mut events = vec![KEvent::new(index, EventType::Focus)];
if let Some(current_focus) = current_focus {
if current_focus != index {
events.push(KEvent::new(current_focus.0, EventType::Blur));
events.push(KEvent::new(current_focus, EventType::Blur));
}
}
if let Ok(mut focus_tree) = context.focus_tree.try_write() {
focus_tree.focus(index);
}
context.focus_tree.focus(index);
self.dispatch_events(events, context, world);
}
}
Expand Down
Loading