Merge branch 'main' into select-on-rename

This commit is contained in:
Nathan Sobo 2022-03-11 15:30:07 -07:00
commit 951fd1ab36
28 changed files with 1063 additions and 257 deletions

View file

@ -740,6 +740,7 @@ type ActionCallback =
type GlobalActionCallback = dyn FnMut(&dyn AnyAction, &mut MutableAppContext);
type SubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext) -> bool>;
type GlobalSubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext)>;
type ObservationCallback = Box<dyn FnMut(&mut MutableAppContext) -> bool>;
type ReleaseObservationCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext)>;
@ -757,6 +758,7 @@ pub struct MutableAppContext {
next_subscription_id: usize,
frame_count: usize,
subscriptions: Arc<Mutex<HashMap<usize, BTreeMap<usize, SubscriptionCallback>>>>,
global_subscriptions: Arc<Mutex<HashMap<TypeId, BTreeMap<usize, GlobalSubscriptionCallback>>>>,
observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, ObservationCallback>>>>,
release_observations: Arc<Mutex<HashMap<usize, BTreeMap<usize, ReleaseObservationCallback>>>>,
presenters_and_platform_windows:
@ -804,6 +806,7 @@ impl MutableAppContext {
next_subscription_id: 0,
frame_count: 0,
subscriptions: Default::default(),
global_subscriptions: Default::default(),
observations: Default::default(),
release_observations: Default::default(),
presenters_and_platform_windows: HashMap::new(),
@ -1062,6 +1065,12 @@ impl MutableAppContext {
self.foreground_platform.prompt_for_new_path(directory)
}
pub fn emit_global<E: Any>(&mut self, payload: E) {
self.pending_effects.push_back(Effect::GlobalEvent {
payload: Box::new(payload),
});
}
pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
where
E: Entity,
@ -1075,6 +1084,31 @@ impl MutableAppContext {
})
}
pub fn subscribe_global<E, F>(&mut self, mut callback: F) -> Subscription
where
E: Any,
F: 'static + FnMut(&E, &mut Self),
{
let id = post_inc(&mut self.next_subscription_id);
let type_id = TypeId::of::<E>();
self.global_subscriptions
.lock()
.entry(type_id)
.or_default()
.insert(
id,
Box::new(move |payload, cx| {
let payload = payload.downcast_ref().expect("downcast is type safe");
callback(payload, cx)
}),
);
Subscription::GlobalSubscription {
id,
type_id,
subscriptions: Some(Arc::downgrade(&self.global_subscriptions)),
}
}
pub fn observe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
where
E: Entity,
@ -1573,6 +1607,7 @@ impl MutableAppContext {
if let Some(effect) = self.pending_effects.pop_front() {
match effect {
Effect::Event { entity_id, payload } => self.emit_event(entity_id, payload),
Effect::GlobalEvent { payload } => self.emit_global_event(payload),
Effect::ModelNotification { model_id } => {
self.notify_model_observers(model_id)
}
@ -1700,6 +1735,16 @@ impl MutableAppContext {
}
}
fn emit_global_event(&mut self, payload: Box<dyn Any>) {
let type_id = (&*payload).type_id();
let callbacks = self.global_subscriptions.lock().remove(&type_id);
if let Some(callbacks) = callbacks {
for (_, mut callback) in callbacks {
callback(payload.as_ref(), self)
}
}
}
fn notify_model_observers(&mut self, observed_id: usize) {
let callbacks = self.observations.lock().remove(&observed_id);
if let Some(callbacks) = callbacks {
@ -2071,6 +2116,9 @@ pub enum Effect {
entity_id: usize,
payload: Box<dyn Any>,
},
GlobalEvent {
payload: Box<dyn Any>,
},
ModelNotification {
model_id: usize,
},
@ -2104,6 +2152,10 @@ impl Debug for Effect {
.debug_struct("Effect::Event")
.field("entity_id", entity_id)
.finish(),
Effect::GlobalEvent { payload, .. } => f
.debug_struct("Effect::GlobalEvent")
.field("type_id", &(&*payload).type_id())
.finish(),
Effect::ModelNotification { model_id } => f
.debug_struct("Effect::ModelNotification")
.field("model_id", model_id)
@ -3762,6 +3814,12 @@ pub enum Subscription {
entity_id: usize,
subscriptions: Option<Weak<Mutex<HashMap<usize, BTreeMap<usize, SubscriptionCallback>>>>>,
},
GlobalSubscription {
id: usize,
type_id: TypeId,
subscriptions:
Option<Weak<Mutex<HashMap<TypeId, BTreeMap<usize, GlobalSubscriptionCallback>>>>>,
},
Observation {
id: usize,
entity_id: usize,
@ -3781,6 +3839,9 @@ impl Subscription {
Subscription::Subscription { subscriptions, .. } => {
subscriptions.take();
}
Subscription::GlobalSubscription { subscriptions, .. } => {
subscriptions.take();
}
Subscription::Observation { observations, .. } => {
observations.take();
}
@ -3794,6 +3855,28 @@ impl Subscription {
impl Drop for Subscription {
fn drop(&mut self) {
match self {
Subscription::Subscription {
id,
entity_id,
subscriptions,
} => {
if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
if let Some(subscriptions) = subscriptions.lock().get_mut(entity_id) {
subscriptions.remove(id);
}
}
}
Subscription::GlobalSubscription {
id,
type_id,
subscriptions,
} => {
if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
if let Some(subscriptions) = subscriptions.lock().get_mut(type_id) {
subscriptions.remove(id);
}
}
}
Subscription::Observation {
id,
entity_id,
@ -3816,17 +3899,6 @@ impl Drop for Subscription {
}
}
}
Subscription::Subscription {
id,
entity_id,
subscriptions,
} => {
if let Some(subscriptions) = subscriptions.as_ref().and_then(Weak::upgrade) {
if let Some(subscriptions) = subscriptions.lock().get_mut(entity_id) {
subscriptions.remove(id);
}
}
}
}
}
}

View file

@ -3,13 +3,15 @@ use serde_json::json;
use crate::{
geometry::vector::Vector2F, DebugContext, Element, ElementBox, Event, EventContext,
LayoutContext, PaintContext, SizeConstraint,
LayoutContext, NavigationDirection, PaintContext, SizeConstraint,
};
pub struct EventHandler {
child: ElementBox,
capture: Option<Box<dyn FnMut(&Event, RectF, &mut EventContext) -> bool>>,
mouse_down: Option<Box<dyn FnMut(&mut EventContext) -> bool>>,
right_mouse_down: Option<Box<dyn FnMut(&mut EventContext) -> bool>>,
navigate_mouse_down: Option<Box<dyn FnMut(NavigationDirection, &mut EventContext) -> bool>>,
}
impl EventHandler {
@ -18,6 +20,8 @@ impl EventHandler {
child,
capture: None,
mouse_down: None,
right_mouse_down: None,
navigate_mouse_down: None,
}
}
@ -29,6 +33,22 @@ impl EventHandler {
self
}
pub fn on_right_mouse_down<F>(mut self, callback: F) -> Self
where
F: 'static + FnMut(&mut EventContext) -> bool,
{
self.right_mouse_down = Some(Box::new(callback));
self
}
pub fn on_navigate_mouse_down<F>(mut self, callback: F) -> Self
where
F: 'static + FnMut(NavigationDirection, &mut EventContext) -> bool,
{
self.navigate_mouse_down = Some(Box::new(callback));
self
}
pub fn capture<F>(mut self, callback: F) -> Self
where
F: 'static + FnMut(&Event, RectF, &mut EventContext) -> bool,
@ -87,6 +107,26 @@ impl Element for EventHandler {
}
false
}
Event::RightMouseDown { position, .. } => {
if let Some(callback) = self.right_mouse_down.as_mut() {
if bounds.contains_point(*position) {
return callback(cx);
}
}
false
}
Event::NavigateMouseDown {
position,
direction,
..
} => {
if let Some(callback) = self.navigate_mouse_down.as_mut() {
if bounds.contains_point(*position) {
return callback(*direction, cx);
}
}
false
}
_ => false,
}
}

View file

@ -29,7 +29,7 @@ pub mod keymap;
pub mod platform;
pub use gpui_macros::test;
pub use platform::FontSystem;
pub use platform::{Event, PathPromptOptions, Platform, PromptLevel};
pub use platform::{Event, NavigationDirection, PathPromptOptions, Platform, PromptLevel};
pub use presenter::{
Axis, DebugContext, EventContext, LayoutContext, PaintContext, SizeConstraint, Vector2FExt,
};

View file

@ -19,7 +19,7 @@ use crate::{
};
use anyhow::Result;
use async_task::Runnable;
pub use event::Event;
pub use event::{Event, NavigationDirection};
use postage::oneshot;
use std::{
any::Any,

View file

@ -1,5 +1,11 @@
use crate::{geometry::vector::Vector2F, keymap::Keystroke};
#[derive(Copy, Clone, Debug)]
pub enum NavigationDirection {
Back,
Forward,
}
#[derive(Clone, Debug)]
pub enum Event {
KeyDown {
@ -26,6 +32,30 @@ pub enum Event {
LeftMouseDragged {
position: Vector2F,
},
RightMouseDown {
position: Vector2F,
ctrl: bool,
alt: bool,
shift: bool,
cmd: bool,
click_count: usize,
},
RightMouseUp {
position: Vector2F,
},
NavigateMouseDown {
position: Vector2F,
direction: NavigationDirection,
ctrl: bool,
alt: bool,
shift: bool,
cmd: bool,
click_count: usize,
},
NavigateMouseUp {
position: Vector2F,
direction: NavigationDirection,
},
MouseMoved {
position: Vector2F,
left_mouse_down: bool,

View file

@ -1,4 +1,8 @@
use crate::{geometry::vector::vec2f, keymap::Keystroke, platform::Event};
use crate::{
geometry::vector::vec2f,
keymap::Keystroke,
platform::{Event, NavigationDirection},
};
use cocoa::{
appkit::{NSEvent, NSEventModifierFlags, NSEventType},
base::{id, nil, YES},
@ -125,6 +129,64 @@ impl Event {
window_height - native_event.locationInWindow().y as f32,
),
}),
NSEventType::NSRightMouseDown => {
let modifiers = native_event.modifierFlags();
window_height.map(|window_height| Self::RightMouseDown {
position: vec2f(
native_event.locationInWindow().x as f32,
window_height - native_event.locationInWindow().y as f32,
),
ctrl: modifiers.contains(NSEventModifierFlags::NSControlKeyMask),
alt: modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask),
shift: modifiers.contains(NSEventModifierFlags::NSShiftKeyMask),
cmd: modifiers.contains(NSEventModifierFlags::NSCommandKeyMask),
click_count: native_event.clickCount() as usize,
})
}
NSEventType::NSRightMouseUp => window_height.map(|window_height| Self::RightMouseUp {
position: vec2f(
native_event.locationInWindow().x as f32,
window_height - native_event.locationInWindow().y as f32,
),
}),
NSEventType::NSOtherMouseDown => {
let direction = match native_event.buttonNumber() {
3 => NavigationDirection::Back,
4 => NavigationDirection::Forward,
// Other mouse buttons aren't tracked currently
_ => return None,
};
let modifiers = native_event.modifierFlags();
window_height.map(|window_height| Self::NavigateMouseDown {
position: vec2f(
native_event.locationInWindow().x as f32,
window_height - native_event.locationInWindow().y as f32,
),
direction,
ctrl: modifiers.contains(NSEventModifierFlags::NSControlKeyMask),
alt: modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask),
shift: modifiers.contains(NSEventModifierFlags::NSShiftKeyMask),
cmd: modifiers.contains(NSEventModifierFlags::NSCommandKeyMask),
click_count: native_event.clickCount() as usize,
})
}
NSEventType::NSOtherMouseUp => {
let direction = match native_event.buttonNumber() {
3 => NavigationDirection::Back,
4 => NavigationDirection::Forward,
// Other mouse buttons aren't tracked currently
_ => return None,
};
window_height.map(|window_height| Self::NavigateMouseUp {
position: vec2f(
native_event.locationInWindow().x as f32,
window_height - native_event.locationInWindow().y as f32,
),
direction,
})
}
NSEventType::NSLeftMouseDragged => {
window_height.map(|window_height| Self::LeftMouseDragged {
position: vec2f(

View file

@ -95,6 +95,22 @@ unsafe fn build_classes() {
sel!(mouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(rightMouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(rightMouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(otherMouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(otherMouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseMoved:),
handle_view_event as extern "C" fn(&Object, Sel, id),

View file

@ -186,7 +186,7 @@ pub struct Run {
pub glyphs: Vec<Glyph>,
}
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct Glyph {
pub id: GlyphId,
pub position: Vector2F,
@ -210,10 +210,14 @@ impl Line {
self.layout.width
}
pub fn font_size(&self) -> f32 {
self.layout.font_size
}
pub fn x_for_index(&self, index: usize) -> f32 {
for run in &self.layout.runs {
for glyph in &run.glyphs {
if glyph.index == index {
if glyph.index >= index {
return glyph.position.x();
}
}
@ -221,6 +225,18 @@ impl Line {
self.layout.width
}
pub fn font_for_index(&self, index: usize) -> Option<FontId> {
for run in &self.layout.runs {
for glyph in &run.glyphs {
if glyph.index >= index {
return Some(run.font_id);
}
}
}
None
}
pub fn index_for_x(&self, x: f32) -> Option<usize> {
if x >= self.layout.width {
None