mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-29 05:11:44 +03:00
Merge pull request #889 from zed-industries/cursor-style-revamp
Apply cursor styles during paint and make editor's cursor an I-Beam
This commit is contained in:
commit
ddc45eb24e
@ -89,10 +89,6 @@
|
|||||||
"top": 7
|
"top": 7
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"margin": {
|
|
||||||
"bottom": 52,
|
|
||||||
"top": 52
|
|
||||||
},
|
|
||||||
"shadow": {
|
"shadow": {
|
||||||
"blur": 16,
|
"blur": 16,
|
||||||
"color": "#00000052",
|
"color": "#00000052",
|
||||||
@ -158,6 +154,13 @@
|
|||||||
"right": 8
|
"right": 8
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"modal": {
|
||||||
|
"margin": {
|
||||||
|
"bottom": 52,
|
||||||
|
"top": 52
|
||||||
|
},
|
||||||
|
"cursor": "Arrow"
|
||||||
|
},
|
||||||
"left_sidebar": {
|
"left_sidebar": {
|
||||||
"width": 30,
|
"width": 30,
|
||||||
"background": "#1c1c1c",
|
"background": "#1c1c1c",
|
||||||
|
@ -89,10 +89,6 @@
|
|||||||
"top": 7
|
"top": 7
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"margin": {
|
|
||||||
"bottom": 52,
|
|
||||||
"top": 52
|
|
||||||
},
|
|
||||||
"shadow": {
|
"shadow": {
|
||||||
"blur": 16,
|
"blur": 16,
|
||||||
"color": "#0000001f",
|
"color": "#0000001f",
|
||||||
@ -158,6 +154,13 @@
|
|||||||
"right": 8
|
"right": 8
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"modal": {
|
||||||
|
"margin": {
|
||||||
|
"bottom": 52,
|
||||||
|
"top": 52
|
||||||
|
},
|
||||||
|
"cursor": "Arrow"
|
||||||
|
},
|
||||||
"left_sidebar": {
|
"left_sidebar": {
|
||||||
"width": 30,
|
"width": 30,
|
||||||
"background": "#f8f8f8",
|
"background": "#f8f8f8",
|
||||||
|
@ -16,6 +16,7 @@ use gpui::{
|
|||||||
PathBuilder,
|
PathBuilder,
|
||||||
},
|
},
|
||||||
json::{self, ToJson},
|
json::{self, ToJson},
|
||||||
|
platform::CursorStyle,
|
||||||
text_layout::{self, Line, RunStyle, TextLayoutCache},
|
text_layout::{self, Line, RunStyle, TextLayoutCache},
|
||||||
AppContext, Axis, Border, Element, ElementBox, Event, EventContext, LayoutContext,
|
AppContext, Axis, Border, Element, ElementBox, Event, EventContext, LayoutContext,
|
||||||
MutableAppContext, PaintContext, Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
|
MutableAppContext, PaintContext, Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
|
||||||
@ -329,6 +330,7 @@ impl EditorElement {
|
|||||||
let content_origin = bounds.origin() + vec2f(layout.gutter_margin, 0.);
|
let content_origin = bounds.origin() + vec2f(layout.gutter_margin, 0.);
|
||||||
|
|
||||||
cx.scene.push_layer(Some(bounds));
|
cx.scene.push_layer(Some(bounds));
|
||||||
|
cx.scene.push_cursor_style(bounds, CursorStyle::IBeam);
|
||||||
|
|
||||||
for (range, color) in &layout.highlighted_ranges {
|
for (range, color) in &layout.highlighted_ranges {
|
||||||
self.paint_highlighted_range(
|
self.paint_highlighted_range(
|
||||||
|
@ -161,29 +161,25 @@ impl View for GoToLine {
|
|||||||
self.max_point.row + 1
|
self.max_point.row + 1
|
||||||
);
|
);
|
||||||
|
|
||||||
Align::new(
|
ConstrainedBox::new(
|
||||||
ConstrainedBox::new(
|
Container::new(
|
||||||
Container::new(
|
Flex::new(Axis::Vertical)
|
||||||
Flex::new(Axis::Vertical)
|
.with_child(
|
||||||
.with_child(
|
Container::new(ChildView::new(&self.line_editor).boxed())
|
||||||
Container::new(ChildView::new(&self.line_editor).boxed())
|
.with_style(theme.input_editor.container)
|
||||||
.with_style(theme.input_editor.container)
|
.boxed(),
|
||||||
.boxed(),
|
)
|
||||||
)
|
.with_child(
|
||||||
.with_child(
|
Container::new(Label::new(label, theme.empty.label.clone()).boxed())
|
||||||
Container::new(Label::new(label, theme.empty.label.clone()).boxed())
|
.with_style(theme.empty.container)
|
||||||
.with_style(theme.empty.container)
|
.boxed(),
|
||||||
.boxed(),
|
)
|
||||||
)
|
.boxed(),
|
||||||
.boxed(),
|
|
||||||
)
|
|
||||||
.with_style(theme.container)
|
|
||||||
.boxed(),
|
|
||||||
)
|
)
|
||||||
.with_max_width(500.0)
|
.with_style(theme.container)
|
||||||
.boxed(),
|
.boxed(),
|
||||||
)
|
)
|
||||||
.top()
|
.with_max_width(500.0)
|
||||||
.named("go to line")
|
.named("go to line")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
elements::ElementBox,
|
elements::ElementBox,
|
||||||
executor::{self, Task},
|
executor::{self, Task},
|
||||||
keymap::{self, Binding, Keystroke},
|
keymap::{self, Binding, Keystroke},
|
||||||
platform::{self, CursorStyle, Platform, PromptLevel, WindowOptions},
|
platform::{self, Platform, PromptLevel, WindowOptions},
|
||||||
presenter::Presenter,
|
presenter::Presenter,
|
||||||
util::post_inc,
|
util::post_inc,
|
||||||
AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache,
|
AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache,
|
||||||
@ -31,10 +31,7 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
rc::{self, Rc},
|
rc::{self, Rc},
|
||||||
sync::{
|
sync::{Arc, Weak},
|
||||||
atomic::{AtomicUsize, Ordering::SeqCst},
|
|
||||||
Arc, Weak,
|
|
||||||
},
|
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -766,7 +763,6 @@ pub struct MutableAppContext {
|
|||||||
pending_global_notifications: HashSet<TypeId>,
|
pending_global_notifications: HashSet<TypeId>,
|
||||||
pending_flushes: usize,
|
pending_flushes: usize,
|
||||||
flushing_effects: bool,
|
flushing_effects: bool,
|
||||||
next_cursor_style_handle_id: Arc<AtomicUsize>,
|
|
||||||
halt_action_dispatch: bool,
|
halt_action_dispatch: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -818,7 +814,6 @@ impl MutableAppContext {
|
|||||||
pending_global_notifications: HashSet::new(),
|
pending_global_notifications: HashSet::new(),
|
||||||
pending_flushes: 0,
|
pending_flushes: 0,
|
||||||
flushing_effects: false,
|
flushing_effects: false,
|
||||||
next_cursor_style_handle_id: Default::default(),
|
|
||||||
halt_action_dispatch: false,
|
halt_action_dispatch: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1949,16 +1944,6 @@ impl MutableAppContext {
|
|||||||
self.presenters_and_platform_windows = presenters;
|
self.presenters_and_platform_windows = presenters;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_cursor_style(&mut self, style: CursorStyle) -> CursorStyleHandle {
|
|
||||||
self.platform.set_cursor_style(style);
|
|
||||||
let id = self.next_cursor_style_handle_id.fetch_add(1, SeqCst);
|
|
||||||
CursorStyleHandle {
|
|
||||||
id,
|
|
||||||
next_cursor_style_handle_id: self.next_cursor_style_handle_id.clone(),
|
|
||||||
platform: self.platform(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_subscription_effect(
|
fn handle_subscription_effect(
|
||||||
&mut self,
|
&mut self,
|
||||||
entity_id: usize,
|
entity_id: usize,
|
||||||
@ -4452,20 +4437,6 @@ impl<T> Drop for ElementStateHandle<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CursorStyleHandle {
|
|
||||||
id: usize,
|
|
||||||
next_cursor_style_handle_id: Arc<AtomicUsize>,
|
|
||||||
platform: Arc<dyn Platform>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for CursorStyleHandle {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if self.id + 1 == self.next_cursor_style_handle_id.load(SeqCst) {
|
|
||||||
self.platform.set_cursor_style(CursorStyle::Arrow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub enum Subscription {
|
pub enum Subscription {
|
||||||
Subscription {
|
Subscription {
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
use pathfinder_geometry::rect::RectF;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
color::Color,
|
color::Color,
|
||||||
geometry::{
|
geometry::{
|
||||||
deserialize_vec2f,
|
deserialize_vec2f,
|
||||||
|
rect::RectF,
|
||||||
vector::{vec2f, Vector2F},
|
vector::{vec2f, Vector2F},
|
||||||
},
|
},
|
||||||
json::ToJson,
|
json::ToJson,
|
||||||
|
platform::CursorStyle,
|
||||||
scene::{self, Border, Quad},
|
scene::{self, Border, Quad},
|
||||||
Element, ElementBox, Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
|
Element, ElementBox, Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
|
||||||
};
|
};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Deserialize)]
|
#[derive(Clone, Copy, Debug, Default, Deserialize)]
|
||||||
pub struct ContainerStyle {
|
pub struct ContainerStyle {
|
||||||
@ -27,6 +27,8 @@ pub struct ContainerStyle {
|
|||||||
pub corner_radius: f32,
|
pub corner_radius: f32,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub shadow: Option<Shadow>,
|
pub shadow: Option<Shadow>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub cursor: Option<CursorStyle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Container {
|
pub struct Container {
|
||||||
@ -128,6 +130,11 @@ impl Container {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_cursor(mut self, style: CursorStyle) -> Self {
|
||||||
|
self.style.cursor = Some(style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn margin_size(&self) -> Vector2F {
|
fn margin_size(&self) -> Vector2F {
|
||||||
vec2f(
|
vec2f(
|
||||||
self.style.margin.left + self.style.margin.right,
|
self.style.margin.left + self.style.margin.right,
|
||||||
@ -205,6 +212,10 @@ impl Element for Container {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(style) = self.style.cursor {
|
||||||
|
cx.scene.push_cursor_style(quad_bounds, style);
|
||||||
|
}
|
||||||
|
|
||||||
let child_origin =
|
let child_origin =
|
||||||
quad_bounds.origin() + vec2f(self.style.padding.left, self.style.padding.top);
|
quad_bounds.origin() + vec2f(self.style.padding.left, self.style.padding.top);
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ use crate::{
|
|||||||
vector::{vec2f, Vector2F},
|
vector::{vec2f, Vector2F},
|
||||||
},
|
},
|
||||||
platform::CursorStyle,
|
platform::CursorStyle,
|
||||||
CursorStyleHandle, DebugContext, Element, ElementBox, ElementStateContext, ElementStateHandle,
|
DebugContext, Element, ElementBox, ElementStateContext, ElementStateHandle, Event,
|
||||||
Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
|
EventContext, LayoutContext, PaintContext, SizeConstraint,
|
||||||
};
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
@ -25,7 +25,6 @@ pub struct MouseState {
|
|||||||
pub hovered: bool,
|
pub hovered: bool,
|
||||||
pub clicked: bool,
|
pub clicked: bool,
|
||||||
prev_drag_position: Option<Vector2F>,
|
prev_drag_position: Option<Vector2F>,
|
||||||
cursor_style_handle: Option<CursorStyleHandle>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MouseEventHandler {
|
impl MouseEventHandler {
|
||||||
@ -72,6 +71,14 @@ impl MouseEventHandler {
|
|||||||
self.padding = padding;
|
self.padding = padding;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hit_bounds(&self, bounds: RectF) -> RectF {
|
||||||
|
RectF::from_points(
|
||||||
|
bounds.origin() - vec2f(self.padding.left, self.padding.top),
|
||||||
|
bounds.lower_right() + vec2f(self.padding.right, self.padding.bottom),
|
||||||
|
)
|
||||||
|
.round_out()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Element for MouseEventHandler {
|
impl Element for MouseEventHandler {
|
||||||
@ -93,6 +100,10 @@ impl Element for MouseEventHandler {
|
|||||||
_: &mut Self::LayoutState,
|
_: &mut Self::LayoutState,
|
||||||
cx: &mut PaintContext,
|
cx: &mut PaintContext,
|
||||||
) -> Self::PaintState {
|
) -> Self::PaintState {
|
||||||
|
if let Some(cursor_style) = self.cursor_style {
|
||||||
|
cx.scene
|
||||||
|
.push_cursor_style(self.hit_bounds(bounds), cursor_style);
|
||||||
|
}
|
||||||
self.child.paint(bounds.origin(), visible_bounds, cx);
|
self.child.paint(bounds.origin(), visible_bounds, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,19 +116,13 @@ impl Element for MouseEventHandler {
|
|||||||
_: &mut Self::PaintState,
|
_: &mut Self::PaintState,
|
||||||
cx: &mut EventContext,
|
cx: &mut EventContext,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let cursor_style = self.cursor_style;
|
let hit_bounds = self.hit_bounds(visible_bounds);
|
||||||
let mouse_down_handler = self.mouse_down_handler.as_mut();
|
let mouse_down_handler = self.mouse_down_handler.as_mut();
|
||||||
let click_handler = self.click_handler.as_mut();
|
let click_handler = self.click_handler.as_mut();
|
||||||
let drag_handler = self.drag_handler.as_mut();
|
let drag_handler = self.drag_handler.as_mut();
|
||||||
|
|
||||||
let handled_in_child = self.child.dispatch_event(event, cx);
|
let handled_in_child = self.child.dispatch_event(event, cx);
|
||||||
|
|
||||||
let hit_bounds = RectF::from_points(
|
|
||||||
visible_bounds.origin() - vec2f(self.padding.left, self.padding.top),
|
|
||||||
visible_bounds.lower_right() + vec2f(self.padding.right, self.padding.bottom),
|
|
||||||
)
|
|
||||||
.round_out();
|
|
||||||
|
|
||||||
self.state.update(cx, |state, cx| match event {
|
self.state.update(cx, |state, cx| match event {
|
||||||
Event::MouseMoved {
|
Event::MouseMoved {
|
||||||
position,
|
position,
|
||||||
@ -127,16 +132,6 @@ impl Element for MouseEventHandler {
|
|||||||
let mouse_in = hit_bounds.contains_point(*position);
|
let mouse_in = hit_bounds.contains_point(*position);
|
||||||
if state.hovered != mouse_in {
|
if state.hovered != mouse_in {
|
||||||
state.hovered = mouse_in;
|
state.hovered = mouse_in;
|
||||||
if let Some(cursor_style) = cursor_style {
|
|
||||||
if !state.clicked {
|
|
||||||
if state.hovered {
|
|
||||||
state.cursor_style_handle =
|
|
||||||
Some(cx.set_cursor_style(cursor_style));
|
|
||||||
} else {
|
|
||||||
state.cursor_style_handle = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -160,9 +155,6 @@ impl Element for MouseEventHandler {
|
|||||||
state.prev_drag_position = None;
|
state.prev_drag_position = None;
|
||||||
if !handled_in_child && state.clicked {
|
if !handled_in_child && state.clicked {
|
||||||
state.clicked = false;
|
state.clicked = false;
|
||||||
if !state.hovered {
|
|
||||||
state.cursor_style_handle = None;
|
|
||||||
}
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
if let Some(handler) = click_handler {
|
if let Some(handler) = click_handler {
|
||||||
if hit_bounds.contains_point(*position) {
|
if hit_bounds.contains_point(*position) {
|
||||||
|
@ -21,6 +21,7 @@ use anyhow::{anyhow, Result};
|
|||||||
use async_task::Runnable;
|
use async_task::Runnable;
|
||||||
pub use event::{Event, NavigationDirection};
|
pub use event::{Event, NavigationDirection};
|
||||||
use postage::oneshot;
|
use postage::oneshot;
|
||||||
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
@ -125,11 +126,12 @@ pub enum PromptLevel {
|
|||||||
Critical,
|
Critical,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, Deserialize)]
|
||||||
pub enum CursorStyle {
|
pub enum CursorStyle {
|
||||||
Arrow,
|
Arrow,
|
||||||
ResizeLeftRight,
|
ResizeLeftRight,
|
||||||
PointingHand,
|
PointingHand,
|
||||||
|
IBeam,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
@ -583,6 +583,7 @@ impl platform::Platform for MacPlatform {
|
|||||||
CursorStyle::Arrow => msg_send![class!(NSCursor), arrowCursor],
|
CursorStyle::Arrow => msg_send![class!(NSCursor), arrowCursor],
|
||||||
CursorStyle::ResizeLeftRight => msg_send![class!(NSCursor), resizeLeftRightCursor],
|
CursorStyle::ResizeLeftRight => msg_send![class!(NSCursor), resizeLeftRightCursor],
|
||||||
CursorStyle::PointingHand => msg_send![class!(NSCursor), pointingHandCursor],
|
CursorStyle::PointingHand => msg_send![class!(NSCursor), pointingHandCursor],
|
||||||
|
CursorStyle::IBeam => msg_send![class!(NSCursor), IBeamCursor],
|
||||||
};
|
};
|
||||||
let _: () = msg_send![cursor, set];
|
let _: () = msg_send![cursor, set];
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
font_cache::FontCache,
|
font_cache::FontCache,
|
||||||
geometry::rect::RectF,
|
geometry::rect::RectF,
|
||||||
json::{self, ToJson},
|
json::{self, ToJson},
|
||||||
platform::Event,
|
platform::{CursorStyle, Event},
|
||||||
text_layout::TextLayoutCache,
|
text_layout::TextLayoutCache,
|
||||||
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox,
|
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox,
|
||||||
ElementStateContext, Entity, FontSystem, ModelHandle, ReadModel, ReadView, Scene,
|
ElementStateContext, Entity, FontSystem, ModelHandle, ReadModel, ReadView, Scene,
|
||||||
@ -22,6 +22,7 @@ pub struct Presenter {
|
|||||||
window_id: usize,
|
window_id: usize,
|
||||||
pub(crate) rendered_views: HashMap<usize, ElementBox>,
|
pub(crate) rendered_views: HashMap<usize, ElementBox>,
|
||||||
parents: HashMap<usize, usize>,
|
parents: HashMap<usize, usize>,
|
||||||
|
cursor_styles: Vec<(RectF, CursorStyle)>,
|
||||||
font_cache: Arc<FontCache>,
|
font_cache: Arc<FontCache>,
|
||||||
text_layout_cache: TextLayoutCache,
|
text_layout_cache: TextLayoutCache,
|
||||||
asset_cache: Arc<AssetCache>,
|
asset_cache: Arc<AssetCache>,
|
||||||
@ -42,6 +43,7 @@ impl Presenter {
|
|||||||
window_id,
|
window_id,
|
||||||
rendered_views: cx.render_views(window_id, titlebar_height),
|
rendered_views: cx.render_views(window_id, titlebar_height),
|
||||||
parents: HashMap::new(),
|
parents: HashMap::new(),
|
||||||
|
cursor_styles: Default::default(),
|
||||||
font_cache,
|
font_cache,
|
||||||
text_layout_cache,
|
text_layout_cache,
|
||||||
asset_cache,
|
asset_cache,
|
||||||
@ -118,6 +120,7 @@ impl Presenter {
|
|||||||
RectF::new(Vector2F::zero(), window_size),
|
RectF::new(Vector2F::zero(), window_size),
|
||||||
);
|
);
|
||||||
self.text_layout_cache.finish_frame();
|
self.text_layout_cache.finish_frame();
|
||||||
|
self.cursor_styles = scene.cursor_styles();
|
||||||
|
|
||||||
if let Some(event) = self.last_mouse_moved_event.clone() {
|
if let Some(event) = self.last_mouse_moved_event.clone() {
|
||||||
self.dispatch_event(event, cx)
|
self.dispatch_event(event, cx)
|
||||||
@ -171,8 +174,21 @@ impl Presenter {
|
|||||||
pub fn dispatch_event(&mut self, event: Event, cx: &mut MutableAppContext) {
|
pub fn dispatch_event(&mut self, event: Event, cx: &mut MutableAppContext) {
|
||||||
if let Some(root_view_id) = cx.root_view_id(self.window_id) {
|
if let Some(root_view_id) = cx.root_view_id(self.window_id) {
|
||||||
match event {
|
match event {
|
||||||
Event::MouseMoved { .. } => {
|
Event::MouseMoved {
|
||||||
|
position,
|
||||||
|
left_mouse_down,
|
||||||
|
} => {
|
||||||
self.last_mouse_moved_event = Some(event.clone());
|
self.last_mouse_moved_event = Some(event.clone());
|
||||||
|
|
||||||
|
if !left_mouse_down {
|
||||||
|
cx.platform().set_cursor_style(CursorStyle::Arrow);
|
||||||
|
for (bounds, style) in self.cursor_styles.iter().rev() {
|
||||||
|
if bounds.contains_point(position) {
|
||||||
|
cx.platform().set_cursor_style(*style);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Event::LeftMouseDragged { position } => {
|
Event::LeftMouseDragged { position } => {
|
||||||
self.last_mouse_moved_event = Some(Event::MouseMoved {
|
self.last_mouse_moved_event = Some(Event::MouseMoved {
|
||||||
|
@ -7,6 +7,7 @@ use crate::{
|
|||||||
fonts::{FontId, GlyphId},
|
fonts::{FontId, GlyphId},
|
||||||
geometry::{rect::RectF, vector::Vector2F},
|
geometry::{rect::RectF, vector::Vector2F},
|
||||||
json::ToJson,
|
json::ToJson,
|
||||||
|
platform::CursorStyle,
|
||||||
ImageData,
|
ImageData,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ pub struct Layer {
|
|||||||
image_glyphs: Vec<ImageGlyph>,
|
image_glyphs: Vec<ImageGlyph>,
|
||||||
icons: Vec<Icon>,
|
icons: Vec<Icon>,
|
||||||
paths: Vec<Path>,
|
paths: Vec<Path>,
|
||||||
|
cursor_styles: Vec<(RectF, CursorStyle)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
@ -173,6 +175,13 @@ impl Scene {
|
|||||||
self.stacking_contexts.iter().flat_map(|s| &s.layers)
|
self.stacking_contexts.iter().flat_map(|s| &s.layers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cursor_styles(&self) -> Vec<(RectF, CursorStyle)> {
|
||||||
|
self.layers()
|
||||||
|
.flat_map(|layer| &layer.cursor_styles)
|
||||||
|
.copied()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push_stacking_context(&mut self, clip_bounds: Option<RectF>) {
|
pub fn push_stacking_context(&mut self, clip_bounds: Option<RectF>) {
|
||||||
self.active_stacking_context_stack
|
self.active_stacking_context_stack
|
||||||
.push(self.stacking_contexts.len());
|
.push(self.stacking_contexts.len());
|
||||||
@ -197,6 +206,10 @@ impl Scene {
|
|||||||
self.active_layer().push_quad(quad)
|
self.active_layer().push_quad(quad)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_cursor_style(&mut self, bounds: RectF, style: CursorStyle) {
|
||||||
|
self.active_layer().push_cursor_style(bounds, style);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push_image(&mut self, image: Image) {
|
pub fn push_image(&mut self, image: Image) {
|
||||||
self.active_layer().push_image(image)
|
self.active_layer().push_image(image)
|
||||||
}
|
}
|
||||||
@ -285,6 +298,7 @@ impl Layer {
|
|||||||
glyphs: Default::default(),
|
glyphs: Default::default(),
|
||||||
icons: Default::default(),
|
icons: Default::default(),
|
||||||
paths: Default::default(),
|
paths: Default::default(),
|
||||||
|
cursor_styles: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,6 +316,14 @@ impl Layer {
|
|||||||
self.quads.as_slice()
|
self.quads.as_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn push_cursor_style(&mut self, bounds: RectF, style: CursorStyle) {
|
||||||
|
if let Some(bounds) = bounds.intersection(self.clip_bounds.unwrap_or(bounds)) {
|
||||||
|
if can_draw(bounds) {
|
||||||
|
self.cursor_styles.push((bounds, style));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn push_underline(&mut self, underline: Underline) {
|
fn push_underline(&mut self, underline: Underline) {
|
||||||
if underline.width > 0. {
|
if underline.width > 0. {
|
||||||
self.underlines.push(underline);
|
self.underlines.push(underline);
|
||||||
|
@ -99,8 +99,6 @@ impl<D: PickerDelegate> View for Picker<D> {
|
|||||||
.constrained()
|
.constrained()
|
||||||
.with_max_width(self.max_size.x())
|
.with_max_width(self.max_size.x())
|
||||||
.with_max_height(self.max_size.y())
|
.with_max_height(self.max_size.y())
|
||||||
.aligned()
|
|
||||||
.top()
|
|
||||||
.named("picker")
|
.named("picker")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ pub struct Workspace {
|
|||||||
pub status_bar: StatusBar,
|
pub status_bar: StatusBar,
|
||||||
pub toolbar: Toolbar,
|
pub toolbar: Toolbar,
|
||||||
pub disconnected_overlay: ContainedText,
|
pub disconnected_overlay: ContainedText,
|
||||||
|
pub modal: ContainerStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default)]
|
||||||
|
@ -1983,7 +1983,14 @@ impl View for Workspace {
|
|||||||
content.add_child(self.right_sidebar.render(&theme, cx));
|
content.add_child(self.right_sidebar.render(&theme, cx));
|
||||||
content.boxed()
|
content.boxed()
|
||||||
})
|
})
|
||||||
.with_children(self.modal.as_ref().map(|m| ChildView::new(m).boxed()))
|
.with_children(self.modal.as_ref().map(|m| {
|
||||||
|
ChildView::new(m)
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.workspace.modal)
|
||||||
|
.aligned()
|
||||||
|
.top()
|
||||||
|
.boxed()
|
||||||
|
}))
|
||||||
.flex(1.0, true)
|
.flex(1.0, true)
|
||||||
.boxed(),
|
.boxed(),
|
||||||
)
|
)
|
||||||
|
@ -50,10 +50,6 @@ export default function selectorModal(theme: Theme): Object {
|
|||||||
top: 7,
|
top: 7,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
margin: {
|
|
||||||
bottom: 52,
|
|
||||||
top: 52,
|
|
||||||
},
|
|
||||||
shadow: shadow(theme),
|
shadow: shadow(theme),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,13 @@ export default function workspace(theme: Theme) {
|
|||||||
leaderBorderWidth: 2.0,
|
leaderBorderWidth: 2.0,
|
||||||
tab,
|
tab,
|
||||||
activeTab,
|
activeTab,
|
||||||
|
modal: {
|
||||||
|
margin: {
|
||||||
|
bottom: 52,
|
||||||
|
top: 52,
|
||||||
|
},
|
||||||
|
cursor: "Arrow"
|
||||||
|
},
|
||||||
leftSidebar: {
|
leftSidebar: {
|
||||||
...sidebar,
|
...sidebar,
|
||||||
border: border(theme, "primary", { right: true }),
|
border: border(theme, "primary", { right: true }),
|
||||||
|
Loading…
Reference in New Issue
Block a user