sensors now run in correct order
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
use crate::prelude::*;
|
||||
use cosmic_text::{Attrs, Cursor, Family, FontSystem, Metrics, Motion, Shaping};
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
use winit::{
|
||||
event::KeyEvent,
|
||||
keyboard::{Key, NamedKey},
|
||||
};
|
||||
|
||||
pub struct TextEdit {
|
||||
pub attrs: TextAttrs,
|
||||
@@ -178,6 +182,41 @@ impl<'a> TextEditCtx<'a> {
|
||||
pub fn deselect(&mut self) {
|
||||
self.text.cursor = None;
|
||||
}
|
||||
|
||||
pub fn apply_event(&mut self, event: &KeyEvent) -> TextInputResult {
|
||||
match &event.logical_key {
|
||||
Key::Named(named) => match named {
|
||||
NamedKey::Backspace => self.backspace(),
|
||||
NamedKey::Delete => self.delete(),
|
||||
NamedKey::Space => self.insert(" "),
|
||||
NamedKey::Enter => self.newline(),
|
||||
NamedKey::ArrowRight => self.motion(Motion::Right),
|
||||
NamedKey::ArrowLeft => self.motion(Motion::Left),
|
||||
NamedKey::ArrowUp => self.motion(Motion::Up),
|
||||
NamedKey::ArrowDown => self.motion(Motion::Down),
|
||||
NamedKey::Escape => {
|
||||
self.deselect();
|
||||
return TextInputResult::Unfocus;
|
||||
}
|
||||
_ => return TextInputResult::Unused,
|
||||
},
|
||||
Key::Character(text) => self.insert(text),
|
||||
_ => return TextInputResult::Unused,
|
||||
}
|
||||
TextInputResult::Used
|
||||
}
|
||||
}
|
||||
|
||||
pub enum TextInputResult {
|
||||
Used,
|
||||
Unused,
|
||||
Unfocus,
|
||||
}
|
||||
|
||||
impl TextInputResult {
|
||||
pub fn unfocus(&self) -> bool {
|
||||
matches!(self, TextInputResult::Unfocus)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ctx> FnOnce<(&mut Ui<Ctx>,)> for TextEditBuilder {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
layout::{Ui, UiRegion, Vec2},
|
||||
util::{HashMap, Id, bitflags},
|
||||
util::{HashMap, Id, IdVec, bitflags},
|
||||
};
|
||||
|
||||
bitflags!(Sense, Senses, senses {
|
||||
@@ -34,7 +34,7 @@ pub struct Sensor<Ctx> {
|
||||
}
|
||||
|
||||
pub type SensorMap<Ctx> = HashMap<Id, SensorGroup<Ctx>>;
|
||||
pub type ActiveSensors = HashMap<Id, SenseShape>;
|
||||
pub type ActiveSensors = IdVec<SenseShape>;
|
||||
pub type SenseShape = UiRegion;
|
||||
pub struct SensorGroup<Ctx> {
|
||||
pub hover: ActivationState,
|
||||
@@ -59,15 +59,17 @@ pub trait UiCtx {
|
||||
pub fn run_sensors<Ctx: UiCtx>(ctx: &mut Ctx, cursor: &CursorState, window_size: Vec2) {
|
||||
let active = std::mem::take(&mut ctx.ui().active.sensors);
|
||||
let mut map = std::mem::take(&mut ctx.ui().sensor_map);
|
||||
for (id, shape) in active.iter() {
|
||||
for (id, shape) in active.iter().rev() {
|
||||
let group = &mut map.get_mut(id).unwrap();
|
||||
let region = shape.to_screen(window_size);
|
||||
let in_shape = cursor.exists && region.contains(cursor.pos);
|
||||
group.hover.update(in_shape);
|
||||
group.cursor.update(cursor.pressed && in_shape);
|
||||
|
||||
let mut ran = false;
|
||||
for sensor in &mut group.sensors {
|
||||
if should_run(sensor.senses, group.cursor, group.hover) {
|
||||
ran = true;
|
||||
let sctx = SenseCtx {
|
||||
cursor: cursor.pos - region.top_left,
|
||||
size: region.bot_right - region.top_left,
|
||||
@@ -75,6 +77,9 @@ pub fn run_sensors<Ctx: UiCtx>(ctx: &mut Ctx, cursor: &CursorState, window_size:
|
||||
(sensor.f)(ctx, sctx);
|
||||
}
|
||||
}
|
||||
if ran {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ctx.ui().sensor_map = map;
|
||||
ctx.ui().active.sensors = active;
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use app::App;
|
||||
use cosmic_text::{Family, Motion};
|
||||
use cosmic_text::Family;
|
||||
use render::Renderer;
|
||||
use senses::*;
|
||||
use ui::prelude::*;
|
||||
use winit::{
|
||||
event::WindowEvent,
|
||||
event_loop::ActiveEventLoop,
|
||||
keyboard::{Key, NamedKey},
|
||||
window::Window,
|
||||
};
|
||||
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
|
||||
|
||||
use crate::testing::input::Input;
|
||||
|
||||
@@ -207,29 +202,9 @@ impl Client {
|
||||
WindowEvent::KeyboardInput { event, .. } => {
|
||||
if let Some(sel) = &self.selected
|
||||
&& event.state.is_pressed()
|
||||
&& self.ui.text(sel).apply_event(&event).unfocus()
|
||||
{
|
||||
let w = &mut self.ui.text(sel);
|
||||
match &event.logical_key {
|
||||
Key::Named(named) => match named {
|
||||
NamedKey::Backspace => w.backspace(),
|
||||
NamedKey::Delete => w.delete(),
|
||||
NamedKey::Space => w.insert(" "),
|
||||
NamedKey::Enter => w.newline(),
|
||||
NamedKey::ArrowRight => w.motion(Motion::Right),
|
||||
NamedKey::ArrowLeft => w.motion(Motion::Left),
|
||||
NamedKey::ArrowUp => w.motion(Motion::Up),
|
||||
NamedKey::ArrowDown => w.motion(Motion::Down),
|
||||
NamedKey::Escape => {
|
||||
w.deselect();
|
||||
self.selected = None;
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
Key::Character(text) => {
|
||||
w.insert(text);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
self.selected = None;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
|
||||
76
src/util/idvec.rs
Normal file
76
src/util/idvec.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
use std::ops::{Deref, Index, IndexMut};
|
||||
|
||||
use crate::util::{HashMap, id::Id};
|
||||
|
||||
/// a vec that's indexed with permanent ids rather than an offset
|
||||
pub struct IdVec<T> {
|
||||
map: HashMap<Id, usize>,
|
||||
vec: Vec<(Id, T)>,
|
||||
}
|
||||
|
||||
impl<T> IdVec<T> {
|
||||
pub fn insert(&mut self, id: Id, v: T) {
|
||||
let idx = self.vec.len();
|
||||
self.map.insert(id.duplicate(), idx);
|
||||
self.vec.push((id, v));
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, id: &Id) -> Option<T> {
|
||||
let i = self.map.remove(id)?;
|
||||
let v = self.vec.remove(i).1;
|
||||
for (id, _) in &self.vec[i..] {
|
||||
*self.map.get_mut(id).unwrap() -= 1;
|
||||
}
|
||||
Some(v)
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.map.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.map.is_empty()
|
||||
}
|
||||
|
||||
pub fn idx(&self, id: &Id) -> usize {
|
||||
self.map[id]
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.map.clear();
|
||||
self.vec.clear();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for IdVec<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
map: Default::default(),
|
||||
vec: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<&Id> for IdVec<T> {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, id: &Id) -> &Self::Output {
|
||||
let i = self.idx(id);
|
||||
&self.vec[i].1
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IndexMut<&Id> for IdVec<T> {
|
||||
fn index_mut(&mut self, id: &Id) -> &mut Self::Output {
|
||||
let i = self.idx(id);
|
||||
&mut self.vec[i].1
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for IdVec<T> {
|
||||
type Target = Vec<(Id, T)>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.vec
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
mod bitflags;
|
||||
mod borrow;
|
||||
mod id;
|
||||
mod idvec;
|
||||
mod math;
|
||||
mod refcount;
|
||||
|
||||
pub(crate) use bitflags::*;
|
||||
pub(crate) use borrow::*;
|
||||
pub(crate) use id::*;
|
||||
pub(crate) use idvec::*;
|
||||
pub(crate) use math::*;
|
||||
pub(crate) use refcount::*;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user