This commit is contained in:
Nathan Sobo 2023-04-11 18:21:56 -06:00
parent 3de8fe0f87
commit e115baa60c
94 changed files with 1477 additions and 1310 deletions

View File

@ -5,7 +5,7 @@ use gpui::{
actions, actions,
elements::*, elements::*,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
Action, AppContext, Entity, ModelHandle, RenderContext, View, ViewContext, ViewHandle, Action, AppContext, Entity, ModelHandle, View, ViewContext, ViewHandle,
}; };
use language::{LanguageRegistry, LanguageServerBinaryStatus}; use language::{LanguageRegistry, LanguageServerBinaryStatus};
use project::{LanguageServerProgress, Project}; use project::{LanguageServerProgress, Project};
@ -172,7 +172,7 @@ impl ActivityIndicator {
.flatten() .flatten()
} }
fn content_to_render(&mut self, cx: &mut RenderContext<Self>) -> Content { fn content_to_render(&mut self, cx: &mut ViewContext<Self>) -> Content {
// Show any language server has pending activity. // Show any language server has pending activity.
let mut pending_work = self.pending_language_server_work(cx); let mut pending_work = self.pending_language_server_work(cx);
if let Some(PendingWork { if let Some(PendingWork {
@ -314,7 +314,7 @@ impl View for ActivityIndicator {
"ActivityIndicator" "ActivityIndicator"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let Content { let Content {
icon, icon,
message, message,

View File

@ -26,7 +26,7 @@ impl View for UpdateNotification {
"UpdateNotification" "UpdateNotification"
} }
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox { fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> gpui::ElementBox {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
let theme = &theme.update_notification; let theme = &theme.update_notification;

View File

@ -1,6 +1,6 @@
use gpui::{ use gpui::{
elements::*, platform::MouseButton, AppContext, Entity, RenderContext, Subscription, View, elements::*, platform::MouseButton, AppContext, Entity, Subscription, View, ViewContext,
ViewContext, ViewHandle, ViewHandle,
}; };
use itertools::Itertools; use itertools::Itertools;
use search::ProjectSearchView; use search::ProjectSearchView;
@ -41,7 +41,7 @@ impl View for Breadcrumbs {
"Breadcrumbs" "Breadcrumbs"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let active_item = match &self.active_item { let active_item = match &self.active_item {
Some(active_item) => active_item, Some(active_item) => active_item,
None => return Empty::new().boxed(), None => return Empty::new().boxed(),

View File

@ -16,8 +16,8 @@ use gpui::{
impl_internal_actions, impl_internal_actions,
json::{self, ToJson}, json::{self, ToJson},
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
AppContext, Entity, ImageData, ModelHandle, RenderContext, Subscription, View, ViewContext, AppContext, Entity, ImageData, ModelHandle, Subscription, View, ViewContext, ViewHandle,
ViewHandle, WeakViewHandle, WeakViewHandle,
}; };
use settings::Settings; use settings::Settings;
use std::{ops::Range, sync::Arc}; use std::{ops::Range, sync::Arc};
@ -68,7 +68,7 @@ impl View for CollabTitlebarItem {
"CollabTitlebarItem" "CollabTitlebarItem"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let workspace = if let Some(workspace) = self.workspace.upgrade(cx) { let workspace = if let Some(workspace) = self.workspace.upgrade(cx) {
workspace workspace
} else { } else {
@ -325,7 +325,7 @@ impl CollabTitlebarItem {
fn render_toggle_contacts_button( fn render_toggle_contacts_button(
&self, &self,
theme: &Theme, theme: &Theme,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let titlebar = &theme.workspace.titlebar; let titlebar = &theme.workspace.titlebar;
@ -390,7 +390,7 @@ impl CollabTitlebarItem {
&self, &self,
theme: &Theme, theme: &Theme,
room: &ModelHandle<Room>, room: &ModelHandle<Room>,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let icon; let icon;
let tooltip; let tooltip;
@ -436,7 +436,7 @@ impl CollabTitlebarItem {
&self, &self,
workspace: &ViewHandle<Workspace>, workspace: &ViewHandle<Workspace>,
theme: &Theme, theme: &Theme,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> Option<ElementBox> { ) -> Option<ElementBox> {
let project = workspace.read(cx).project(); let project = workspace.read(cx).project();
if project.read(cx).is_remote() { if project.read(cx).is_remote() {
@ -491,7 +491,7 @@ impl CollabTitlebarItem {
) )
} }
fn render_user_menu_button(&self, theme: &Theme, cx: &mut RenderContext<Self>) -> ElementBox { fn render_user_menu_button(&self, theme: &Theme, cx: &mut ViewContext<Self>) -> ElementBox {
let titlebar = &theme.workspace.titlebar; let titlebar = &theme.workspace.titlebar;
Stack::new() Stack::new()
@ -535,7 +535,7 @@ impl CollabTitlebarItem {
.boxed() .boxed()
} }
fn render_sign_in_button(&self, theme: &Theme, cx: &mut RenderContext<Self>) -> ElementBox { fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext<Self>) -> ElementBox {
let titlebar = &theme.workspace.titlebar; let titlebar = &theme.workspace.titlebar;
MouseEventHandler::<SignIn>::new(0, cx, |state, _| { MouseEventHandler::<SignIn>::new(0, cx, |state, _| {
let style = titlebar.sign_in_prompt.style_for(state, false); let style = titlebar.sign_in_prompt.style_for(state, false);
@ -554,7 +554,7 @@ impl CollabTitlebarItem {
fn render_contacts_popover_host<'a>( fn render_contacts_popover_host<'a>(
&'a self, &'a self,
_theme: &'a theme::Titlebar, _theme: &'a theme::Titlebar,
cx: &'a RenderContext<Self>, cx: &'a ViewContext<Self>,
) -> Option<ElementBox> { ) -> Option<ElementBox> {
self.contacts_popover.as_ref().map(|popover| { self.contacts_popover.as_ref().map(|popover| {
Overlay::new(ChildView::new(popover, cx).boxed()) Overlay::new(ChildView::new(popover, cx).boxed())
@ -573,7 +573,7 @@ impl CollabTitlebarItem {
workspace: &ViewHandle<Workspace>, workspace: &ViewHandle<Workspace>,
theme: &Theme, theme: &Theme,
room: &ModelHandle<Room>, room: &ModelHandle<Room>,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> Vec<ElementBox> { ) -> Vec<ElementBox> {
let mut participants = room let mut participants = room
.read(cx) .read(cx)
@ -615,7 +615,7 @@ impl CollabTitlebarItem {
theme: &Theme, theme: &Theme,
user: &Arc<User>, user: &Arc<User>,
peer_id: PeerId, peer_id: PeerId,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let replica_id = workspace.read(cx).project().read(cx).replica_id(); let replica_id = workspace.read(cx).project().read(cx).replica_id();
Container::new(self.render_face_pile( Container::new(self.render_face_pile(
@ -639,7 +639,7 @@ impl CollabTitlebarItem {
location: Option<ParticipantLocation>, location: Option<ParticipantLocation>,
workspace: &ViewHandle<Workspace>, workspace: &ViewHandle<Workspace>,
theme: &Theme, theme: &Theme,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let project_id = workspace.read(cx).project().read(cx).remote_id(); let project_id = workspace.read(cx).project().read(cx).remote_id();
let room = ActiveCall::global(cx).read(cx).room(); let room = ActiveCall::global(cx).read(cx).room();
@ -804,7 +804,7 @@ impl CollabTitlebarItem {
workspace: &ViewHandle<Workspace>, workspace: &ViewHandle<Workspace>,
location: Option<ParticipantLocation>, location: Option<ParticipantLocation>,
mut style: AvatarStyle, mut style: AvatarStyle,
cx: &RenderContext<Self>, cx: &ViewContext<Self>,
) -> AvatarStyle { ) -> AvatarStyle {
if let Some(location) = location { if let Some(location) = location {
if let ParticipantLocation::SharedProject { project_id } = location { if let ParticipantLocation::SharedProject { project_id } = location {
@ -840,7 +840,7 @@ impl CollabTitlebarItem {
fn render_connection_status( fn render_connection_status(
&self, &self,
status: &client::Status, status: &client::Status,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> Option<ElementBox> { ) -> Option<ElementBox> {
enum ConnectionStatusButton {} enum ConnectionStatusButton {}
@ -927,7 +927,7 @@ impl Element for AvatarRibbon {
path.line_to(bounds.upper_right() - vec2f(bounds.height(), 0.)); path.line_to(bounds.upper_right() - vec2f(bounds.height(), 0.));
path.curve_to(bounds.lower_right(), bounds.upper_right()); path.curve_to(bounds.lower_right(), bounds.upper_right());
path.line_to(bounds.lower_left()); path.line_to(bounds.lower_left());
cx.scene.push_path(path.build(self.color, None)); scene.push_path(path.build(self.color, None));
} }
fn rect_for_text_range( fn rect_for_text_range(

View File

@ -1,10 +1,7 @@
use call::ActiveCall; use call::ActiveCall;
use client::UserStore; use client::UserStore;
use gpui::Action; use gpui::Action;
use gpui::{ use gpui::{actions, elements::*, platform::MouseButton, Entity, ModelHandle, View, ViewContext};
actions, elements::*, platform::MouseButton, Entity, ModelHandle, RenderContext, View,
ViewContext,
};
use settings::Settings; use settings::Settings;
use crate::collab_titlebar_item::ToggleCollaboratorList; use crate::collab_titlebar_item::ToggleCollaboratorList;
@ -21,7 +18,7 @@ enum Collaborator {
actions!(collaborator_list_popover, [NoOp]); actions!(collaborator_list_popover, [NoOp]);
pub(crate) struct CollaboratorListPopover { pub(crate) struct CollaboratorListPopover {
list_state: ListState, list_state: ListState<Self>,
} }
impl Entity for CollaboratorListPopover { impl Entity for CollaboratorListPopover {
@ -33,7 +30,7 @@ impl View for CollaboratorListPopover {
"CollaboratorListPopover" "CollaboratorListPopover"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
MouseEventHandler::<Self>::new(0, cx, |_, _| { MouseEventHandler::<Self>::new(0, cx, |_, _| {
@ -120,7 +117,7 @@ fn render_collaborator_list_entry<UA: Action + Clone, IA: Action + Clone>(
icon: Svg, icon: Svg,
icon_action: IA, icon_action: IA,
icon_tooltip: String, icon_tooltip: String,
cx: &mut RenderContext<CollaboratorListPopover>, cx: &mut ViewContext<CollaboratorListPopover>,
) -> ElementBox { ) -> ElementBox {
enum Username {} enum Username {}
enum UsernameTooltip {} enum UsernameTooltip {}

View File

@ -1,7 +1,7 @@
use client::{ContactRequestStatus, User, UserStore}; use client::{ContactRequestStatus, User, UserStore};
use gpui::{ use gpui::{
elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, RenderContext, Task, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, Task, View,
View, ViewContext, ViewHandle, ViewContext, ViewHandle,
}; };
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
use settings::Settings; use settings::Settings;
@ -32,7 +32,7 @@ impl View for ContactFinder {
"ContactFinder" "ContactFinder"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
ChildView::new(&self.picker, cx).boxed() ChildView::new(&self.picker, cx).boxed()
} }

View File

@ -11,7 +11,7 @@ use gpui::{
impl_actions, impl_internal_actions, impl_actions, impl_internal_actions,
keymap_matcher::KeymapContext, keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton, PromptLevel}, platform::{CursorStyle, MouseButton, PromptLevel},
AppContext, Entity, ModelHandle, RenderContext, Subscription, View, ViewContext, ViewHandle, AppContext, Entity, ModelHandle, Subscription, View, ViewContext, ViewHandle,
}; };
use menu::{Confirm, SelectNext, SelectPrev}; use menu::{Confirm, SelectNext, SelectPrev};
use project::Project; use project::Project;
@ -799,7 +799,7 @@ impl ContactList {
is_last: bool, is_last: bool,
is_selected: bool, is_selected: bool,
theme: &theme::ContactList, theme: &theme::ContactList,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let font_cache = cx.font_cache(); let font_cache = cx.font_cache();
let host_avatar_height = theme let host_avatar_height = theme
@ -834,7 +834,7 @@ impl ContactList {
let start_y = bounds.min_y(); let start_y = bounds.min_y();
let end_y = bounds.min_y() + baseline_offset - (cap_height / 2.); let end_y = bounds.min_y() + baseline_offset - (cap_height / 2.);
cx.scene.push_quad(gpui::Quad { scene.push_quad(gpui::Quad {
bounds: RectF::from_points( bounds: RectF::from_points(
vec2f(start_x, start_y), vec2f(start_x, start_y),
vec2f( vec2f(
@ -846,7 +846,7 @@ impl ContactList {
border: gpui::Border::default(), border: gpui::Border::default(),
corner_radius: 0., corner_radius: 0.,
}); });
cx.scene.push_quad(gpui::Quad { scene.push_quad(gpui::Quad {
bounds: RectF::from_points( bounds: RectF::from_points(
vec2f(start_x, end_y), vec2f(start_x, end_y),
vec2f(end_x, end_y + tree_branch.width), vec2f(end_x, end_y + tree_branch.width),
@ -898,7 +898,7 @@ impl ContactList {
is_last: bool, is_last: bool,
is_selected: bool, is_selected: bool,
theme: &theme::ContactList, theme: &theme::ContactList,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let font_cache = cx.font_cache(); let font_cache = cx.font_cache();
let host_avatar_height = theme let host_avatar_height = theme
@ -932,7 +932,7 @@ impl ContactList {
let end_y = let end_y =
bounds.min_y() + baseline_offset - (cap_height / 2.); bounds.min_y() + baseline_offset - (cap_height / 2.);
cx.scene.push_quad(gpui::Quad { scene.push_quad(gpui::Quad {
bounds: RectF::from_points( bounds: RectF::from_points(
vec2f(start_x, start_y), vec2f(start_x, start_y),
vec2f( vec2f(
@ -944,7 +944,7 @@ impl ContactList {
border: gpui::Border::default(), border: gpui::Border::default(),
corner_radius: 0., corner_radius: 0.,
}); });
cx.scene.push_quad(gpui::Quad { scene.push_quad(gpui::Quad {
bounds: RectF::from_points( bounds: RectF::from_points(
vec2f(start_x, end_y), vec2f(start_x, end_y),
vec2f(end_x, end_y + tree_branch.width), vec2f(end_x, end_y + tree_branch.width),
@ -999,7 +999,7 @@ impl ContactList {
theme: &theme::ContactList, theme: &theme::ContactList,
is_selected: bool, is_selected: bool,
is_collapsed: bool, is_collapsed: bool,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
enum Header {} enum Header {}
enum LeaveCallContactList {} enum LeaveCallContactList {}
@ -1077,7 +1077,7 @@ impl ContactList {
project: &ModelHandle<Project>, project: &ModelHandle<Project>,
theme: &theme::ContactList, theme: &theme::ContactList,
is_selected: bool, is_selected: bool,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let online = contact.online; let online = contact.online;
let busy = contact.busy || calling; let busy = contact.busy || calling;
@ -1194,7 +1194,7 @@ impl ContactList {
theme: &theme::ContactList, theme: &theme::ContactList,
is_incoming: bool, is_incoming: bool,
is_selected: bool, is_selected: bool,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
enum Decline {} enum Decline {}
enum Accept {} enum Accept {}
@ -1331,7 +1331,7 @@ impl View for ContactList {
cx cx
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
enum AddContact {} enum AddContact {}
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();

View File

@ -3,8 +3,7 @@ use std::sync::Arc;
use crate::notifications::render_user_notification; use crate::notifications::render_user_notification;
use client::{ContactEventKind, User, UserStore}; use client::{ContactEventKind, User, UserStore};
use gpui::{ use gpui::{
elements::*, impl_internal_actions, AppContext, Entity, ModelHandle, RenderContext, View, elements::*, impl_internal_actions, AppContext, Entity, ModelHandle, View, ViewContext,
ViewContext,
}; };
use workspace::notifications::Notification; use workspace::notifications::Notification;
@ -43,7 +42,7 @@ impl View for ContactNotification {
"ContactNotification" "ContactNotification"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
match self.kind { match self.kind {
ContactEventKind::Requested => render_user_notification( ContactEventKind::Requested => render_user_notification(
self.user.clone(), self.user.clone(),

View File

@ -1,8 +1,8 @@
use crate::{contact_finder::ContactFinder, contact_list::ContactList, ToggleContactsMenu}; use crate::{contact_finder::ContactFinder, contact_list::ContactList, ToggleContactsMenu};
use client::UserStore; use client::UserStore;
use gpui::{ use gpui::{
actions, elements::*, platform::MouseButton, AppContext, Entity, ModelHandle, RenderContext, actions, elements::*, platform::MouseButton, AppContext, Entity, ModelHandle, View,
View, ViewContext, ViewHandle, ViewContext, ViewHandle,
}; };
use project::Project; use project::Project;
use settings::Settings; use settings::Settings;
@ -91,7 +91,7 @@ impl View for ContactsPopover {
"ContactsPopover" "ContactsPopover"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
let child = match &self.child { let child = match &self.child {
Child::ContactList(child) => ChildView::new(child, cx), Child::ContactList(child) => ChildView::new(child, cx),

View File

@ -37,7 +37,7 @@ impl Element for FacePile {
let mut width = 0.; let mut width = 0.;
for face in &mut self.faces { for face in &mut self.faces {
width += face.layout(constraint, cx).x(); width += face.layout(constraint, view, cx).x();
} }
width -= self.overlap * self.faces.len().saturating_sub(1) as f32; width -= self.overlap * self.faces.len().saturating_sub(1) as f32;
@ -60,7 +60,7 @@ impl Element for FacePile {
let size = face.size(); let size = face.size();
origin_x -= size.x(); origin_x -= size.x();
cx.paint_layer(None, |cx| { cx.paint_layer(None, |cx| {
face.paint(vec2f(origin_x, origin_y), visible_bounds, cx); face.paint(scene, vec2f(origin_x, origin_y), visible_bounds, view, cx);
}); });
origin_x += self.overlap; origin_x += self.overlap;
} }

View File

@ -6,7 +6,7 @@ use gpui::{
geometry::{rect::RectF, vector::vec2f}, geometry::{rect::RectF, vector::vec2f},
impl_internal_actions, impl_internal_actions,
platform::{CursorStyle, MouseButton, WindowBounds, WindowKind, WindowOptions}, platform::{CursorStyle, MouseButton, WindowBounds, WindowKind, WindowOptions},
AppContext, Entity, RenderContext, View, ViewContext, AppContext, Entity, View, ViewContext,
}; };
use settings::Settings; use settings::Settings;
use util::ResultExt; use util::ResultExt;
@ -99,7 +99,7 @@ impl IncomingCallNotification {
} }
} }
fn render_caller(&self, cx: &mut RenderContext<Self>) -> ElementBox { fn render_caller(&self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = &cx.global::<Settings>().theme.incoming_call_notification; let theme = &cx.global::<Settings>().theme.incoming_call_notification;
let default_project = proto::ParticipantProject::default(); let default_project = proto::ParticipantProject::default();
let initial_project = self let initial_project = self
@ -165,7 +165,7 @@ impl IncomingCallNotification {
.boxed() .boxed()
} }
fn render_buttons(&self, cx: &mut RenderContext<Self>) -> ElementBox { fn render_buttons(&self, cx: &mut ViewContext<Self>) -> ElementBox {
enum Accept {} enum Accept {}
enum Decline {} enum Decline {}
@ -222,7 +222,7 @@ impl View for IncomingCallNotification {
"IncomingCallNotification" "IncomingCallNotification"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> gpui::ElementBox {
let background = cx let background = cx
.global::<Settings>() .global::<Settings>()
.theme .theme

View File

@ -2,7 +2,7 @@ use client::User;
use gpui::{ use gpui::{
elements::*, elements::*,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
Action, Element, ElementBox, RenderContext, View, Action, Element, ElementBox, View, ViewContext,
}; };
use settings::Settings; use settings::Settings;
use std::sync::Arc; use std::sync::Arc;
@ -16,7 +16,7 @@ pub fn render_user_notification<V: View, A: Action + Clone>(
body: Option<&'static str>, body: Option<&'static str>,
dismiss_action: A, dismiss_action: A,
buttons: Vec<(&'static str, Box<dyn Action>)>, buttons: Vec<(&'static str, Box<dyn Action>)>,
cx: &mut RenderContext<V>, cx: &mut ViewContext<V>,
) -> ElementBox { ) -> ElementBox {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
let theme = &theme.contact_notification; let theme = &theme.contact_notification;

View File

@ -6,7 +6,7 @@ use gpui::{
elements::*, elements::*,
geometry::{rect::RectF, vector::vec2f}, geometry::{rect::RectF, vector::vec2f},
platform::{CursorStyle, MouseButton, WindowBounds, WindowKind, WindowOptions}, platform::{CursorStyle, MouseButton, WindowBounds, WindowKind, WindowOptions},
AppContext, Entity, RenderContext, View, ViewContext, AppContext, Entity, View, ViewContext,
}; };
use settings::Settings; use settings::Settings;
use std::sync::Arc; use std::sync::Arc;
@ -104,7 +104,7 @@ impl ProjectSharedNotification {
cx.remove_window(window_id); cx.remove_window(window_id);
} }
fn render_owner(&self, cx: &mut RenderContext<Self>) -> ElementBox { fn render_owner(&self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = &cx.global::<Settings>().theme.project_shared_notification; let theme = &cx.global::<Settings>().theme.project_shared_notification;
Flex::row() Flex::row()
.with_children(self.owner.avatar.clone().map(|avatar| { .with_children(self.owner.avatar.clone().map(|avatar| {
@ -164,7 +164,7 @@ impl ProjectSharedNotification {
.boxed() .boxed()
} }
fn render_buttons(&self, cx: &mut RenderContext<Self>) -> ElementBox { fn render_buttons(&self, cx: &mut ViewContext<Self>) -> ElementBox {
enum Open {} enum Open {}
enum Dismiss {} enum Dismiss {}
@ -227,7 +227,7 @@ impl View for ProjectSharedNotification {
"ProjectSharedNotification" "ProjectSharedNotification"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> gpui::ElementBox {
let background = cx let background = cx
.global::<Settings>() .global::<Settings>()
.theme .theme

View File

@ -3,7 +3,7 @@ use gpui::{
color::Color, color::Color,
elements::{MouseEventHandler, Svg}, elements::{MouseEventHandler, Svg},
platform::{Appearance, MouseButton}, platform::{Appearance, MouseButton},
AppContext, Element, ElementBox, Entity, RenderContext, View, AppContext, Element, ElementBox, Entity, View, ViewContext,
}; };
use settings::Settings; use settings::Settings;
@ -40,7 +40,7 @@ impl View for SharingStatusIndicator {
"SharingStatusIndicator" "SharingStatusIndicator"
} }
fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> ElementBox {
let color = match cx.appearance { let color = match cx.appearance {
Appearance::Light | Appearance::VibrantLight => Color::black(), Appearance::Light | Appearance::VibrantLight => Color::black(),
Appearance::Dark | Appearance::VibrantDark => Color::white(), Appearance::Dark | Appearance::VibrantDark => Color::white(),

View File

@ -4,8 +4,7 @@ use gpui::{
actions, actions,
elements::{ChildView, Flex, Label, ParentElement}, elements::{ChildView, Flex, Label, ParentElement},
keymap_matcher::Keystroke, keymap_matcher::Keystroke,
Action, AnyViewHandle, AppContext, Element, Entity, MouseState, RenderContext, View, Action, AnyViewHandle, AppContext, Element, Entity, MouseState, View, ViewContext, ViewHandle,
ViewContext, ViewHandle,
}; };
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
use settings::Settings; use settings::Settings;
@ -80,9 +79,7 @@ impl CommandPalette {
fn toggle(_: &mut Workspace, _: &Toggle, cx: &mut ViewContext<Workspace>) { fn toggle(_: &mut Workspace, _: &Toggle, cx: &mut ViewContext<Workspace>) {
let workspace = cx.handle(); let workspace = cx.handle();
let window_id = cx.window_id(); let window_id = cx.window_id();
let focused_view_id = cx let focused_view_id = cx.focused_view_id().unwrap_or_else(|| workspace.id());
.focused_view_id(window_id)
.unwrap_or_else(|| workspace.id());
cx.as_mut().defer(move |cx| { cx.as_mut().defer(move |cx| {
let this = cx.add_view(&workspace, |cx| Self::new(focused_view_id, cx)); let this = cx.add_view(&workspace, |cx| Self::new(focused_view_id, cx));
@ -128,7 +125,7 @@ impl View for CommandPalette {
"CommandPalette" "CommandPalette"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> gpui::ElementBox {
ChildView::new(&self.picker, cx).boxed() ChildView::new(&self.picker, cx).boxed()
} }

View File

@ -4,15 +4,13 @@ use gpui::{
impl_internal_actions, impl_internal_actions,
keymap_matcher::KeymapContext, keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
Action, AnyViewHandle, AppContext, Axis, Entity, MouseState, RenderContext, SizeConstraint, Action, AnyViewHandle, AppContext, Axis, Entity, MouseState, SizeConstraint, Subscription,
Subscription, View, ViewContext, View, ViewContext,
}; };
use menu::*; use menu::*;
use settings::Settings; use settings::Settings;
use std::{any::TypeId, borrow::Cow, time::Duration}; use std::{any::TypeId, borrow::Cow, time::Duration};
pub type StaticItem = Box<dyn Fn(&mut AppContext) -> ElementBox>;
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
struct Clicked; struct Clicked;
@ -28,8 +26,10 @@ pub fn init(cx: &mut AppContext) {
cx.add_action(ContextMenu::cancel); cx.add_action(ContextMenu::cancel);
} }
pub type StaticItem = Box<dyn Fn(&mut AppContext) -> ElementBox<ContextMenu>>;
type ContextMenuItemBuilder = type ContextMenuItemBuilder =
Box<dyn Fn(&mut MouseState, &theme::ContextMenuItem) -> ElementBox>; Box<dyn Fn(&mut MouseState, &theme::ContextMenuItem) -> ElementBox<ContextMenu>>;
pub enum ContextMenuItemLabel { pub enum ContextMenuItemLabel {
String(Cow<'static, str>), String(Cow<'static, str>),
@ -142,7 +142,7 @@ impl View for ContextMenu {
cx cx
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox<Self> {
if !self.visible { if !self.visible {
return Empty::new().boxed(); return Empty::new().boxed();
} }
@ -152,10 +152,10 @@ impl View for ContextMenu {
let expanded_menu = self let expanded_menu = self
.render_menu(cx) .render_menu(cx)
.constrained() .constrained()
.dynamically(move |constraint, cx| { .dynamically(move |constraint, view, cx| {
SizeConstraint::strict_along( SizeConstraint::strict_along(
Axis::Horizontal, Axis::Horizontal,
collapsed_menu.layout(constraint, cx).x(), collapsed_menu.layout(constraint, view, cx).x(),
) )
}) })
.boxed(); .boxed();
@ -315,7 +315,7 @@ impl ContextMenu {
self.visible = true; self.visible = true;
self.show_count += 1; self.show_count += 1;
if !cx.is_self_focused() { if !cx.is_self_focused() {
self.previously_focused_view_id = cx.focused_view_id(cx.window_id()); self.previously_focused_view_id = cx.focused_view_id();
} }
cx.focus_self(); cx.focus_self();
} else { } else {
@ -328,7 +328,7 @@ impl ContextMenu {
self.position_mode = mode; self.position_mode = mode;
} }
fn render_menu_for_measurement(&self, cx: &mut RenderContext<Self>) -> impl Element { fn render_menu_for_measurement(&self, cx: &mut ViewContext<Self>) -> impl Element<ContextMenu> {
let window_id = cx.window_id(); let window_id = cx.window_id();
let style = cx.global::<Settings>().theme.context_menu.clone(); let style = cx.global::<Settings>().theme.context_menu.clone();
Flex::row() Flex::row()
@ -415,14 +415,14 @@ impl ContextMenu {
.with_style(style.container) .with_style(style.container)
} }
fn render_menu(&self, cx: &mut RenderContext<Self>) -> impl Element { fn render_menu(&self, cx: &mut ViewContext<Self>) -> impl Element<ContextMenu> {
enum Menu {} enum Menu {}
enum MenuItem {} enum MenuItem {}
let style = cx.global::<Settings>().theme.context_menu.clone(); let style = cx.global::<Settings>().theme.context_menu.clone();
let window_id = cx.window_id(); let window_id = cx.window_id();
MouseEventHandler::<Menu>::new(0, cx, |_, cx| { MouseEventHandler::<Menu, ContextMenu>::new(0, cx, |_, cx| {
Flex::column() Flex::column()
.with_children(self.items.iter().enumerate().map(|(ix, item)| { .with_children(self.items.iter().enumerate().map(|(ix, item)| {
match item { match item {
@ -436,7 +436,7 @@ impl ContextMenu {
} }
}; };
MouseEventHandler::<MenuItem>::new(ix, cx, |state, _| { MouseEventHandler::<MenuItem, ContextMenu>::new(ix, cx, |state, _| {
let style = let style =
style.item.style_for(state, Some(ix) == self.selected_index); style.item.style_for(state, Some(ix) == self.selected_index);
@ -467,14 +467,14 @@ impl ContextMenu {
.boxed() .boxed()
}) })
.with_cursor_style(CursorStyle::PointingHand) .with_cursor_style(CursorStyle::PointingHand)
.on_up(MouseButton::Left, |_, _| {}) // Capture these events .on_up(MouseButton::Left, |_, _, _| {}) // Capture these events
.on_down(MouseButton::Left, |_, _| {}) // Capture these events .on_down(MouseButton::Left, |_, _, _| {}) // Capture these events
.on_click(MouseButton::Left, move |_, cx| { .on_click(MouseButton::Left, move |_, _, cx| {
cx.dispatch_action(Clicked); cx.dispatch_action(Clicked);
let window_id = cx.window_id(); let window_id = cx.window_id();
cx.dispatch_any_action_at(window_id, view_id, action.boxed_clone()); cx.dispatch_any_action_at(window_id, view_id, action.boxed_clone());
}) })
.on_drag(MouseButton::Left, |_, _| {}) .on_drag(MouseButton::Left, |_, _, _| {})
.boxed() .boxed()
} }
@ -492,7 +492,7 @@ impl ContextMenu {
.with_style(style.container) .with_style(style.container)
.boxed() .boxed()
}) })
.on_down_out(MouseButton::Left, |_, cx| cx.dispatch_action(Cancel)) .on_down_out(MouseButton::Left, |_, _, cx| cx.dispatch_action(Cancel))
.on_down_out(MouseButton::Right, |_, cx| cx.dispatch_action(Cancel)) .on_down_out(MouseButton::Right, |_, _, cx| cx.dispatch_action(Cancel))
} }
} }

View File

@ -96,7 +96,7 @@ impl CopilotCodeVerification {
fn render_device_code( fn render_device_code(
data: &PromptUserDeviceFlow, data: &PromptUserDeviceFlow,
style: &theme::Copilot, style: &theme::Copilot,
cx: &mut gpui::RenderContext<Self>, cx: &mut gpui::ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let copied = cx let copied = cx
.read_from_clipboard() .read_from_clipboard()
@ -145,7 +145,7 @@ impl CopilotCodeVerification {
fn render_prompting_modal( fn render_prompting_modal(
data: &PromptUserDeviceFlow, data: &PromptUserDeviceFlow,
style: &theme::Copilot, style: &theme::Copilot,
cx: &mut gpui::RenderContext<Self>, cx: &mut gpui::ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
Flex::column() Flex::column()
.with_children([ .with_children([
@ -205,7 +205,7 @@ impl CopilotCodeVerification {
} }
fn render_enabled_modal( fn render_enabled_modal(
style: &theme::Copilot, style: &theme::Copilot,
cx: &mut gpui::RenderContext<Self>, cx: &mut gpui::ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let enabled_style = &style.auth.authorized; let enabled_style = &style.auth.authorized;
Flex::column() Flex::column()
@ -254,7 +254,7 @@ impl CopilotCodeVerification {
} }
fn render_unauthorized_modal( fn render_unauthorized_modal(
style: &theme::Copilot, style: &theme::Copilot,
cx: &mut gpui::RenderContext<Self>, cx: &mut gpui::ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let unauthorized_style = &style.auth.not_authorized; let unauthorized_style = &style.auth.not_authorized;
@ -333,7 +333,7 @@ impl View for CopilotCodeVerification {
cx.notify() cx.notify()
} }
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox { fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> gpui::ElementBox {
let style = cx.global::<Settings>().theme.clone(); let style = cx.global::<Settings>().theme.clone();
modal("Connect Copilot to Zed", &style.copilot.modal, cx, |cx| { modal("Connect Copilot to Zed", &style.copilot.modal, cx, |cx| {

View File

@ -6,8 +6,8 @@ use gpui::{
elements::*, elements::*,
impl_internal_actions, impl_internal_actions,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
AppContext, Element, ElementBox, Entity, MouseState, RenderContext, Subscription, View, AppContext, Element, ElementBox, Entity, MouseState, Subscription, View, ViewContext,
ViewContext, ViewHandle, ViewHandle,
}; };
use settings::{settings_file::SettingsFile, Settings}; use settings::{settings_file::SettingsFile, Settings};
use workspace::{ use workspace::{
@ -91,7 +91,7 @@ impl View for CopilotButton {
"CopilotButton" "CopilotButton"
} }
fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> ElementBox {
let settings = cx.global::<Settings>(); let settings = cx.global::<Settings>();
if !settings.enable_copilot_integration { if !settings.enable_copilot_integration {

View File

@ -11,8 +11,7 @@ use editor::{
}; };
use gpui::{ use gpui::{
actions, elements::*, fonts::TextStyle, impl_internal_actions, serde_json, AnyViewHandle, actions, elements::*, fonts::TextStyle, impl_internal_actions, serde_json, AnyViewHandle,
AppContext, Entity, ModelHandle, RenderContext, Task, View, ViewContext, ViewHandle, AppContext, Entity, ModelHandle, Task, View, ViewContext, ViewHandle, WeakViewHandle,
WeakViewHandle,
}; };
use language::{ use language::{
Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection, Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection,
@ -87,7 +86,7 @@ impl View for ProjectDiagnosticsEditor {
"ProjectDiagnosticsEditor" "ProjectDiagnosticsEditor"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
if self.path_states.is_empty() { if self.path_states.is_empty() {
let theme = &cx.global::<Settings>().theme.project_diagnostics; let theme = &cx.global::<Settings>().theme.project_diagnostics;
Label::new("No problems in workspace", theme.empty_message.clone()) Label::new("No problems in workspace", theme.empty_message.clone())

View File

@ -3,8 +3,8 @@ use editor::{Editor, GoToDiagnostic};
use gpui::{ use gpui::{
elements::*, elements::*,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
serde_json, AppContext, Entity, ModelHandle, RenderContext, Subscription, View, ViewContext, serde_json, AppContext, Entity, ModelHandle, Subscription, View, ViewContext, ViewHandle,
ViewHandle, WeakViewHandle, WeakViewHandle,
}; };
use language::Diagnostic; use language::Diagnostic;
use project::Project; use project::Project;
@ -84,7 +84,7 @@ impl View for DiagnosticIndicator {
"DiagnosticIndicator" "DiagnosticIndicator"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
enum Summary {} enum Summary {}
enum Message {} enum Message {}

View File

@ -6,7 +6,7 @@ use gpui::{
geometry::{rect::RectF, vector::Vector2F}, geometry::{rect::RectF, vector::Vector2F},
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
scene::{MouseDown, MouseDrag}, scene::{MouseDown, MouseDrag},
AppContext, Element, ElementBox, EventContext, RenderContext, View, WeakViewHandle, AppContext, Element, ElementBox, View, ViewContext, WeakViewHandle,
}; };
const DEAD_ZONE: f32 = 4.; const DEAD_ZONE: f32 = 4.;
@ -26,7 +26,7 @@ enum State<V: View> {
region_offset: Vector2F, region_offset: Vector2F,
region: RectF, region: RectF,
payload: Rc<dyn Any + 'static>, payload: Rc<dyn Any + 'static>,
render: Rc<dyn Fn(Rc<dyn Any>, &mut RenderContext<V>) -> ElementBox>, render: Rc<dyn Fn(Rc<dyn Any>, &mut ViewContext<V>) -> ElementBox<V>>,
}, },
Canceled, Canceled,
} }
@ -111,7 +111,7 @@ impl<V: View> DragAndDrop<V> {
}) })
} }
pub fn drag_started(event: MouseDown, cx: &mut EventContext) { pub fn drag_started(event: MouseDown, cx: &mut ViewContext<V>) {
cx.update_global(|this: &mut Self, _| { cx.update_global(|this: &mut Self, _| {
this.currently_dragged = Some(State::Down { this.currently_dragged = Some(State::Down {
region_offset: event.position - event.region.origin(), region_offset: event.position - event.region.origin(),
@ -123,8 +123,8 @@ impl<V: View> DragAndDrop<V> {
pub fn dragging<T: Any>( pub fn dragging<T: Any>(
event: MouseDrag, event: MouseDrag,
payload: Rc<T>, payload: Rc<T>,
cx: &mut EventContext, cx: &mut ViewContext<V>,
render: Rc<impl 'static + Fn(&T, &mut RenderContext<V>) -> ElementBox>, render: Rc<impl 'static + Fn(&T, &mut ViewContext<V>) -> ElementBox<V>>,
) { ) {
let window_id = cx.window_id(); let window_id = cx.window_id();
cx.update_global(|this: &mut Self, cx| { cx.update_global(|this: &mut Self, cx| {
@ -178,7 +178,7 @@ impl<V: View> DragAndDrop<V> {
}); });
} }
pub fn render(cx: &mut RenderContext<V>) -> Option<ElementBox> { pub fn render(cx: &mut ViewContext<V>) -> Option<ElementBox<V>> {
enum DraggedElementHandler {} enum DraggedElementHandler {}
cx.global::<Self>() cx.global::<Self>()
.currently_dragged .currently_dragged
@ -202,20 +202,22 @@ impl<V: View> DragAndDrop<V> {
let position = position - region_offset; let position = position - region_offset;
Some( Some(
Overlay::new( Overlay::new(
MouseEventHandler::<DraggedElementHandler>::new(0, cx, |_, cx| { MouseEventHandler::<DraggedElementHandler, V>::new(
render(payload, cx) 0,
}) cx,
|_, cx| render(payload, cx),
)
.with_cursor_style(CursorStyle::Arrow) .with_cursor_style(CursorStyle::Arrow)
.on_up(MouseButton::Left, |_, cx| { .on_up(MouseButton::Left, |_, _, cx| {
cx.defer(|cx| { cx.defer(|_, cx| {
cx.update_global::<Self, _, _>(|this, cx| { cx.update_global::<Self, _, _>(|this, cx| {
this.finish_dragging(cx) this.finish_dragging(cx)
}); });
}); });
cx.propagate_event(); cx.propagate_event();
}) })
.on_up_out(MouseButton::Left, |_, cx| { .on_up_out(MouseButton::Left, |_, _, cx| {
cx.defer(|cx| { cx.defer(|_, cx| {
cx.update_global::<Self, _, _>(|this, cx| { cx.update_global::<Self, _, _>(|this, cx| {
this.finish_dragging(cx) this.finish_dragging(cx)
}); });
@ -234,22 +236,22 @@ impl<V: View> DragAndDrop<V> {
} }
State::Canceled => Some( State::Canceled => Some(
MouseEventHandler::<DraggedElementHandler>::new(0, cx, |_, _| { MouseEventHandler::<DraggedElementHandler, V>::new(0, cx, |_, _| {
Empty::new() Empty::new()
.constrained() .constrained()
.with_width(0.) .with_width(0.)
.with_height(0.) .with_height(0.)
.boxed() .boxed()
}) })
.on_up(MouseButton::Left, |_, cx| { .on_up(MouseButton::Left, |_, _, cx| {
cx.defer(|cx| { cx.defer(|_, cx| {
cx.update_global::<Self, _, _>(|this, _| { cx.update_global::<Self, _, _>(|this, _| {
this.currently_dragged = None; this.currently_dragged = None;
}); });
}); });
}) })
.on_up_out(MouseButton::Left, |_, cx| { .on_up_out(MouseButton::Left, |_, _, cx| {
cx.defer(|cx| { cx.defer(|_, cx| {
cx.update_global::<Self, _, _>(|this, _| { cx.update_global::<Self, _, _>(|this, _| {
this.currently_dragged = None; this.currently_dragged = None;
}); });
@ -294,32 +296,32 @@ impl<V: View> DragAndDrop<V> {
} }
} }
pub trait Draggable { pub trait Draggable<V: View> {
fn as_draggable<V: View, P: Any>( fn as_draggable<P: Any>(
self, self,
payload: P, payload: P,
render: impl 'static + Fn(&P, &mut RenderContext<V>) -> ElementBox, render: impl 'static + Fn(&P, &mut ViewContext<V>) -> ElementBox<V>,
) -> Self ) -> Self
where where
Self: Sized; Self: Sized;
} }
impl<Tag> Draggable for MouseEventHandler<Tag> { impl<Tag, V: View> Draggable<V> for MouseEventHandler<Tag, V> {
fn as_draggable<V: View, P: Any>( fn as_draggable<P: Any>(
self, self,
payload: P, payload: P,
render: impl 'static + Fn(&P, &mut RenderContext<V>) -> ElementBox, render: impl 'static + Fn(&P, &mut ViewContext<V>) -> ElementBox<V>,
) -> Self ) -> Self
where where
Self: Sized, Self: Sized,
{ {
let payload = Rc::new(payload); let payload = Rc::new(payload);
let render = Rc::new(render); let render = Rc::new(render);
self.on_down(MouseButton::Left, move |e, cx| { self.on_down(MouseButton::Left, move |e, _, cx| {
cx.propagate_event(); cx.propagate_event();
DragAndDrop::<V>::drag_started(e, cx); DragAndDrop::<V>::drag_started(e, cx);
}) })
.on_drag(MouseButton::Left, move |e, cx| { .on_drag(MouseButton::Left, move |e, _, cx| {
let payload = payload.clone(); let payload = payload.clone();
let render = render.clone(); let render = render.clone();
DragAndDrop::<V>::dragging(e, payload, cx, render) DragAndDrop::<V>::dragging(e, payload, cx, render)

View File

@ -4,7 +4,7 @@ use super::{
}; };
use crate::{Anchor, ExcerptId, ExcerptRange, ToPoint as _}; use crate::{Anchor, ExcerptId, ExcerptRange, ToPoint as _};
use collections::{Bound, HashMap, HashSet}; use collections::{Bound, HashMap, HashSet};
use gpui::{fonts::HighlightStyle, RenderContext, ElementBox}; use gpui::{fonts::HighlightStyle, ElementBox, ViewContext};
use language::{BufferSnapshot, Chunk, Patch, Point}; use language::{BufferSnapshot, Chunk, Patch, Point};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{ use std::{
@ -81,7 +81,7 @@ pub enum BlockStyle {
} }
pub struct BlockContext<'a, 'b> { pub struct BlockContext<'a, 'b> {
pub cx: &'b mut RenderContext<'a, crate::Editor>, pub cx: &'b mut ViewContext<'a, crate::Editor>,
pub anchor_x: f32, pub anchor_x: f32,
pub scroll_x: f32, pub scroll_x: f32,
pub gutter_width: f32, pub gutter_width: f32,
@ -933,7 +933,7 @@ impl BlockDisposition {
} }
impl<'a, 'b> Deref for BlockContext<'a, 'b> { impl<'a, 'b> Deref for BlockContext<'a, 'b> {
type Target = RenderContext<'a, crate::Editor>; type Target = ViewContext<'a, crate::Editor>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
self.cx self.cx

View File

@ -42,7 +42,7 @@ use gpui::{
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
serde_json::{self, json}, serde_json::{self, json},
AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity,
ModelHandle, RenderContext, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
}; };
use highlight_matching_bracket::refresh_matching_bracket_highlights; use highlight_matching_bracket::refresh_matching_bracket_highlights;
use hover_popover::{hide_hover, HideHover, HoverState}; use hover_popover::{hide_hover, HideHover, HoverState};
@ -721,7 +721,7 @@ impl ContextMenu {
&self, &self,
cursor_position: DisplayPoint, cursor_position: DisplayPoint,
style: EditorStyle, style: EditorStyle,
cx: &mut RenderContext<Editor>, cx: &mut ViewContext<Editor>,
) -> (DisplayPoint, ElementBox) { ) -> (DisplayPoint, ElementBox) {
match self { match self {
ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)), ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
@ -774,7 +774,7 @@ impl CompletionsMenu {
!self.matches.is_empty() !self.matches.is_empty()
} }
fn render(&self, style: EditorStyle, cx: &mut RenderContext<Editor>) -> ElementBox { fn render(&self, style: EditorStyle, cx: &mut ViewContext<Editor>) -> ElementBox {
enum CompletionTag {} enum CompletionTag {}
let completions = self.completions.clone(); let completions = self.completions.clone();
@ -950,7 +950,7 @@ impl CodeActionsMenu {
&self, &self,
mut cursor_position: DisplayPoint, mut cursor_position: DisplayPoint,
style: EditorStyle, style: EditorStyle,
cx: &mut RenderContext<Editor>, cx: &mut ViewContext<Editor>,
) -> (DisplayPoint, ElementBox) { ) -> (DisplayPoint, ElementBox) {
enum ActionTag {} enum ActionTag {}
@ -2928,7 +2928,7 @@ impl Editor {
&self, &self,
style: &EditorStyle, style: &EditorStyle,
active: bool, active: bool,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> Option<ElementBox> { ) -> Option<ElementBox> {
if self.available_code_actions.is_some() { if self.available_code_actions.is_some() {
enum CodeActions {} enum CodeActions {}
@ -2959,7 +2959,7 @@ impl Editor {
gutter_hovered: bool, gutter_hovered: bool,
line_height: f32, line_height: f32,
gutter_margin: f32, gutter_margin: f32,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> Vec<Option<ElementBox>> { ) -> Vec<Option<ElementBox>> {
enum FoldIndicators {} enum FoldIndicators {}
@ -3027,7 +3027,7 @@ impl Editor {
&self, &self,
cursor_position: DisplayPoint, cursor_position: DisplayPoint,
style: EditorStyle, style: EditorStyle,
cx: &mut RenderContext<Editor>, cx: &mut ViewContext<Editor>,
) -> Option<(DisplayPoint, ElementBox)> { ) -> Option<(DisplayPoint, ElementBox)> {
self.context_menu self.context_menu
.as_ref() .as_ref()
@ -6795,7 +6795,7 @@ impl Entity for Editor {
} }
impl View for Editor { impl View for Editor {
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let style = self.style(cx); let style = self.style(cx);
let font_changed = self.display_map.update(cx, |map, cx| { let font_changed = self.display_map.update(cx, |map, cx| {
map.set_fold_ellipses_color(style.folds.ellipses.text_color); map.set_fold_ellipses_color(style.folds.ellipses.text_color);
@ -6804,7 +6804,7 @@ impl View for Editor {
if font_changed { if font_changed {
let handle = self.handle.clone(); let handle = self.handle.clone();
cx.defer(move |cx| { cx.defer(move |cx: &mut ViewContext<Editor>| {
if let Some(editor) = handle.upgrade(cx) { if let Some(editor) = handle.upgrade(cx) {
editor.update(cx, |editor, cx| { editor.update(cx, |editor, cx| {
hide_hover(editor, &HideHover, cx); hide_hover(editor, &HideHover, cx);

View File

@ -31,8 +31,8 @@ use gpui::{
json::{self, ToJson}, json::{self, ToJson},
platform::{CursorStyle, Modifiers, MouseButton, MouseButtonEvent, MouseMovedEvent}, platform::{CursorStyle, Modifiers, MouseButton, MouseButtonEvent, MouseMovedEvent},
text_layout::{self, Line, RunStyle, TextLayoutCache}, text_layout::{self, Line, RunStyle, TextLayoutCache},
AppContext, Axis, Border, CursorRegion, Element, ElementBox, EventContext, LayoutContext, AppContext, Axis, Border, CursorRegion, Element, ElementBox, MouseRegion, Quad, SceneBuilder,
MouseRegion, PaintContext, Quad, SceneBuilder, SizeConstraint, ViewContext, WeakViewHandle, SizeConstraint, ViewContext, WeakViewHandle,
}; };
use itertools::Itertools; use itertools::Itertools;
use json::json; use json::json;
@ -124,7 +124,7 @@ impl EditorElement {
cx: &mut PaintContext, cx: &mut PaintContext,
) { ) {
enum EditorElementMouseHandlers {} enum EditorElementMouseHandlers {}
cx.scene.push_mouse_region( scene.push_mouse_region(
MouseRegion::new::<EditorElementMouseHandlers>(view.id(), view.id(), visible_bounds) MouseRegion::new::<EditorElementMouseHandlers>(view.id(), view.id(), visible_bounds)
.on_down(MouseButton::Left, { .on_down(MouseButton::Left, {
let position_map = position_map.clone(); let position_map = position_map.clone();
@ -216,7 +216,7 @@ impl EditorElement {
); );
enum GutterHandlers {} enum GutterHandlers {}
cx.scene.push_mouse_region( scene.push_mouse_region(
MouseRegion::new::<GutterHandlers>(view.id(), view.id() + 1, gutter_bounds).on_hover( MouseRegion::new::<GutterHandlers>(view.id(), view.id() + 1, gutter_bounds).on_hover(
|hover, cx| { |hover, cx| {
cx.dispatch_action(GutterHover { cx.dispatch_action(GutterHover {
@ -409,7 +409,7 @@ impl EditorElement {
}: MouseMovedEvent, }: MouseMovedEvent,
position_map: &PositionMap, position_map: &PositionMap,
text_bounds: RectF, text_bounds: RectF,
cx: &mut EventContext, cx: &mut ViewContext<Editor>,
) -> bool { ) -> bool {
// This will be handled more correctly once https://github.com/zed-industries/zed/issues/1218 is completed // This will be handled more correctly once https://github.com/zed-industries/zed/issues/1218 is completed
// Don't trigger hover popover if mouse is hovering over context menu // Don't trigger hover popover if mouse is hovering over context menu
@ -432,7 +432,7 @@ impl EditorElement {
precise: bool, precise: bool,
position_map: &PositionMap, position_map: &PositionMap,
bounds: RectF, bounds: RectF,
cx: &mut EventContext, cx: &mut ViewContext<Editor>,
) -> bool { ) -> bool {
if !bounds.contains_point(position) { if !bounds.contains_point(position) {
return false; return false;
@ -465,21 +465,22 @@ impl EditorElement {
fn paint_background( fn paint_background(
&self, &self,
scene: &mut SceneBuilder,
gutter_bounds: RectF, gutter_bounds: RectF,
text_bounds: RectF, text_bounds: RectF,
layout: &LayoutState, layout: &LayoutState,
cx: &mut PaintContext, cx: &mut ViewContext<Editor>,
) { ) {
let bounds = gutter_bounds.union_rect(text_bounds); let bounds = gutter_bounds.union_rect(text_bounds);
let scroll_top = let scroll_top =
layout.position_map.snapshot.scroll_position().y() * layout.position_map.line_height; layout.position_map.snapshot.scroll_position().y() * layout.position_map.line_height;
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: gutter_bounds, bounds: gutter_bounds,
background: Some(self.style.gutter_background), background: Some(self.style.gutter_background),
border: Border::new(0., Color::transparent_black()), border: Border::new(0., Color::transparent_black()),
corner_radius: 0., corner_radius: 0.,
}); });
cx.scene.push_quad(Quad { c.push_quad(Quad {
bounds: text_bounds, bounds: text_bounds,
background: Some(self.style.background), background: Some(self.style.background),
border: Border::new(0., Color::transparent_black()), border: Border::new(0., Color::transparent_black()),
@ -507,7 +508,7 @@ impl EditorElement {
bounds.width(), bounds.width(),
layout.position_map.line_height * (end_row - start_row + 1) as f32, layout.position_map.line_height * (end_row - start_row + 1) as f32,
); );
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: RectF::new(origin, size), bounds: RectF::new(origin, size),
background: Some(self.style.active_line_background), background: Some(self.style.active_line_background),
border: Border::default(), border: Border::default(),
@ -527,7 +528,7 @@ impl EditorElement {
bounds.width(), bounds.width(),
layout.position_map.line_height * highlighted_rows.len() as f32, layout.position_map.line_height * highlighted_rows.len() as f32,
); );
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: RectF::new(origin, size), bounds: RectF::new(origin, size),
background: Some(self.style.highlighted_line_background), background: Some(self.style.highlighted_line_background),
border: Border::default(), border: Border::default(),
@ -539,9 +540,11 @@ impl EditorElement {
fn paint_gutter( fn paint_gutter(
&mut self, &mut self,
scene: &mut SceneBuilder,
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
layout: &mut LayoutState, layout: &mut LayoutState,
editor: &mut Editor,
cx: &mut PaintContext, cx: &mut PaintContext,
) { ) {
let line_height = layout.position_map.line_height; let line_height = layout.position_map.line_height;
@ -569,7 +572,7 @@ impl EditorElement {
ix as f32 * line_height - (scroll_top % line_height), ix as f32 * line_height - (scroll_top % line_height),
); );
line.paint(line_origin, visible_bounds, line_height, cx); line.paint(scene, line_origin, visible_bounds, line_height, cx);
} }
} }
@ -586,7 +589,7 @@ impl EditorElement {
let indicator_origin = bounds.origin() + position + centering_offset; let indicator_origin = bounds.origin() + position + centering_offset;
indicator.paint(indicator_origin, visible_bounds, cx); indicator.paint(scene, indicator_origin, visible_bounds, editor, cx);
} }
} }
@ -595,7 +598,13 @@ impl EditorElement {
let mut y = *row as f32 * line_height - scroll_top; let mut y = *row as f32 * line_height - scroll_top;
x += ((layout.gutter_padding + layout.gutter_margin) - indicator.size().x()) / 2.; x += ((layout.gutter_padding + layout.gutter_margin) - indicator.size().x()) / 2.;
y += (line_height - indicator.size().y()) / 2.; y += (line_height - indicator.size().y()) / 2.;
indicator.paint(bounds.origin() + vec2f(x, y), visible_bounds, cx); indicator.paint(
scene,
bounds.origin() + vec2f(x, y),
visible_bounds,
editor,
cx,
);
} }
} }
@ -618,7 +627,7 @@ impl EditorElement {
let highlight_size = vec2f(width * 2., end_y - start_y); let highlight_size = vec2f(width * 2., end_y - start_y);
let highlight_bounds = RectF::new(highlight_origin, highlight_size); let highlight_bounds = RectF::new(highlight_origin, highlight_size);
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: highlight_bounds, bounds: highlight_bounds,
background: Some(diff_style.modified), background: Some(diff_style.modified),
border: Border::new(0., Color::transparent_black()), border: Border::new(0., Color::transparent_black()),
@ -651,7 +660,7 @@ impl EditorElement {
let highlight_size = vec2f(width * 2., end_y - start_y); let highlight_size = vec2f(width * 2., end_y - start_y);
let highlight_bounds = RectF::new(highlight_origin, highlight_size); let highlight_bounds = RectF::new(highlight_origin, highlight_size);
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: highlight_bounds, bounds: highlight_bounds,
background: Some(diff_style.deleted), background: Some(diff_style.deleted),
border: Border::new(0., Color::transparent_black()), border: Border::new(0., Color::transparent_black()),
@ -673,7 +682,7 @@ impl EditorElement {
let highlight_size = vec2f(width * 2., end_y - start_y); let highlight_size = vec2f(width * 2., end_y - start_y);
let highlight_bounds = RectF::new(highlight_origin, highlight_size); let highlight_bounds = RectF::new(highlight_origin, highlight_size);
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: highlight_bounds, bounds: highlight_bounds,
background: Some(color), background: Some(color),
border: Border::new(0., Color::transparent_black()), border: Border::new(0., Color::transparent_black()),
@ -684,9 +693,11 @@ impl EditorElement {
fn paint_text( fn paint_text(
&mut self, &mut self,
scene: &mut SceneBuilder,
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
layout: &mut LayoutState, layout: &mut LayoutState,
editor: &mut Editor,
cx: &mut PaintContext, cx: &mut PaintContext,
) { ) {
let view = self.view(cx.app); let view = self.view(cx.app);
@ -700,9 +711,9 @@ impl EditorElement {
let content_origin = bounds.origin() + vec2f(layout.gutter_margin, 0.); let content_origin = bounds.origin() + vec2f(layout.gutter_margin, 0.);
let line_end_overshoot = 0.15 * layout.position_map.line_height; let line_end_overshoot = 0.15 * layout.position_map.line_height;
cx.scene.push_layer(Some(bounds)); scene.push_layer(Some(bounds));
cx.scene.push_cursor_region(CursorRegion { scene.push_cursor_region(CursorRegion {
bounds, bounds,
style: if !view.link_go_to_definition_state.definitions.is_empty() { style: if !view.link_go_to_definition_state.definitions.is_empty() {
CursorStyle::PointingHand CursorStyle::PointingHand
@ -715,6 +726,7 @@ impl EditorElement {
self.style.folds.ellipses.corner_radius_factor * layout.position_map.line_height; self.style.folds.ellipses.corner_radius_factor * layout.position_map.line_height;
for (id, range, color) in layout.fold_ranges.iter() { for (id, range, color) in layout.fold_ranges.iter() {
self.paint_highlighted_range( self.paint_highlighted_range(
scene,
range.clone(), range.clone(),
*color, *color,
fold_corner_radius, fold_corner_radius,
@ -736,7 +748,7 @@ impl EditorElement {
line_end_overshoot, line_end_overshoot,
&layout.position_map, &layout.position_map,
) { ) {
cx.scene.push_cursor_region(CursorRegion { scene.push_cursor_region(CursorRegion {
bounds: bound, bounds: bound,
style: CursorStyle::PointingHand, style: CursorStyle::PointingHand,
}); });
@ -747,7 +759,7 @@ impl EditorElement {
.to_point(&layout.position_map.snapshot.display_snapshot) .to_point(&layout.position_map.snapshot.display_snapshot)
.row; .row;
cx.scene.push_mouse_region( scene.push_mouse_region(
MouseRegion::new::<FoldMarkers>(self.view.id(), *id as usize, bound) MouseRegion::new::<FoldMarkers>(self.view.id(), *id as usize, bound)
.on_click(MouseButton::Left, move |_, cx| { .on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(UnfoldAt { buffer_row }) cx.dispatch_action(UnfoldAt { buffer_row })
@ -760,6 +772,7 @@ impl EditorElement {
for (range, color) in &layout.highlighted_ranges { for (range, color) in &layout.highlighted_ranges {
self.paint_highlighted_range( self.paint_highlighted_range(
scene,
range.clone(), range.clone(),
*color, *color,
0., 0.,
@ -781,6 +794,7 @@ impl EditorElement {
for selection in selections { for selection in selections {
self.paint_highlighted_range( self.paint_highlighted_range(
scene,
selection.range.clone(), selection.range.clone(),
selection_style.selection, selection_style.selection,
corner_radius, corner_radius,
@ -858,6 +872,7 @@ impl EditorElement {
for (ix, line) in layout.position_map.line_layouts.iter().enumerate() { for (ix, line) in layout.position_map.line_layouts.iter().enumerate() {
let row = start_row + ix as u32; let row = start_row + ix as u32;
line.paint( line.paint(
scene,
content_origin content_origin
+ vec2f( + vec2f(
-scroll_left, -scroll_left,
@ -870,14 +885,16 @@ impl EditorElement {
} }
} }
cx.scene.push_layer(Some(bounds)); scene.push_layer(Some(bounds));
scene.paint_layer(Some(bounds), |scene| {
for cursor in cursors { for cursor in cursors {
cursor.paint(content_origin, cx); cursor.paint(scene, content_origin, cx);
} }
cx.scene.pop_layer(); });
if let Some((position, context_menu)) = layout.context_menu.as_mut() { if let Some((position, context_menu)) = layout.context_menu.as_mut() {
cx.scene.push_stacking_context(None, None); scene.push_stacking_context(None, None);
let cursor_row_layout = let cursor_row_layout =
&layout.position_map.line_layouts[(position.row() - start_row) as usize]; &layout.position_map.line_layouts[(position.row() - start_row) as usize];
let x = cursor_row_layout.x_for_index(position.column() as usize) - scroll_left; let x = cursor_row_layout.x_for_index(position.column() as usize) - scroll_left;
@ -897,16 +914,18 @@ impl EditorElement {
} }
context_menu.paint( context_menu.paint(
scene,
list_origin, list_origin,
RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor
editor,
cx, cx,
); );
cx.scene.pop_stacking_context(); scene.pop_stacking_context();
} }
if let Some((position, hover_popovers)) = layout.hover_popovers.as_mut() { if let Some((position, hover_popovers)) = layout.hover_popovers.as_mut() {
cx.scene.push_stacking_context(None, None); scene.push_stacking_context(None, None);
// This is safe because we check on layout whether the required row is available // This is safe because we check on layout whether the required row is available
let hovered_row_layout = let hovered_row_layout =
@ -937,8 +956,10 @@ impl EditorElement {
} }
hover_popover.paint( hover_popover.paint(
scene,
popover_origin, popover_origin,
RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor
editor,
cx, cx,
); );
@ -957,8 +978,10 @@ impl EditorElement {
} }
hover_popover.paint( hover_popover.paint(
scene,
popover_origin, popover_origin,
RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor
editor,
cx, cx,
); );
@ -966,13 +989,19 @@ impl EditorElement {
} }
} }
cx.scene.pop_stacking_context(); scene.pop_stacking_context();
} }
cx.scene.pop_layer(); scene.pop_layer();
} }
fn paint_scrollbar(&mut self, bounds: RectF, layout: &mut LayoutState, cx: &mut PaintContext) { fn paint_scrollbar(
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
layout: &mut LayoutState,
cx: &mut ViewContext<Editor>,
) {
enum ScrollbarMouseHandlers {} enum ScrollbarMouseHandlers {}
if layout.mode != EditorMode::Full { if layout.mode != EditorMode::Full {
return; return;
@ -1008,13 +1037,13 @@ impl EditorElement {
let thumb_bounds = RectF::from_points(vec2f(left, thumb_top), vec2f(right, thumb_bottom)); let thumb_bounds = RectF::from_points(vec2f(left, thumb_top), vec2f(right, thumb_bottom));
if layout.show_scrollbars { if layout.show_scrollbars {
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: track_bounds, bounds: track_bounds,
border: style.track.border, border: style.track.border,
background: style.track.background_color, background: style.track.background_color,
..Default::default() ..Default::default()
}); });
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: thumb_bounds, bounds: thumb_bounds,
border: style.thumb.border, border: style.thumb.border,
background: style.thumb.background_color, background: style.thumb.background_color,
@ -1022,11 +1051,11 @@ impl EditorElement {
}); });
} }
cx.scene.push_cursor_region(CursorRegion { scene.push_cursor_region(CursorRegion {
bounds: track_bounds, bounds: track_bounds,
style: CursorStyle::Arrow, style: CursorStyle::Arrow,
}); });
cx.scene.push_mouse_region( scene.push_mouse_region(
MouseRegion::new::<ScrollbarMouseHandlers>(view.id(), view.id(), track_bounds) MouseRegion::new::<ScrollbarMouseHandlers>(view.id(), view.id(), track_bounds)
.on_move({ .on_move({
let view = view.clone(); let view = view.clone();
@ -1088,6 +1117,7 @@ impl EditorElement {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn paint_highlighted_range( fn paint_highlighted_range(
&self, &self,
scene: &mut SceneBuilder,
range: Range<DisplayPoint>, range: Range<DisplayPoint>,
color: Color, color: Color,
corner_radius: f32, corner_radius: f32,
@ -1097,7 +1127,7 @@ impl EditorElement {
scroll_top: f32, scroll_top: f32,
scroll_left: f32, scroll_left: f32,
bounds: RectF, bounds: RectF,
cx: &mut PaintContext, cx: &mut ViewContext<Self>,
) { ) {
let start_row = layout.visible_display_row_range.start; let start_row = layout.visible_display_row_range.start;
let end_row = layout.visible_display_row_range.end; let end_row = layout.visible_display_row_range.end;
@ -1141,15 +1171,17 @@ impl EditorElement {
.collect(), .collect(),
}; };
highlighted_range.paint(bounds, cx.scene); highlighted_range.paint(bounds, scene);
} }
} }
fn paint_blocks( fn paint_blocks(
&mut self, &mut self,
scene: &mut SceneBuilder,
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
layout: &mut LayoutState, layout: &mut LayoutState,
editor: &mut Editor,
cx: &mut PaintContext, cx: &mut PaintContext,
) { ) {
let scroll_position = layout.position_map.snapshot.scroll_position(); let scroll_position = layout.position_map.snapshot.scroll_position();
@ -1165,7 +1197,9 @@ impl EditorElement {
if !matches!(block.style, BlockStyle::Sticky) { if !matches!(block.style, BlockStyle::Sticky) {
origin += vec2f(-scroll_left, 0.); origin += vec2f(-scroll_left, 0.);
} }
block.element.paint(origin, visible_bounds, cx); block
.element
.paint(scene, origin, visible_bounds, editor, cx);
} }
} }
@ -1384,14 +1418,9 @@ impl EditorElement {
style: &EditorStyle, style: &EditorStyle,
line_layouts: &[text_layout::Line], line_layouts: &[text_layout::Line],
include_root: bool, include_root: bool,
editor: &mut Editor,
cx: &mut LayoutContext, cx: &mut LayoutContext,
) -> (f32, Vec<BlockLayout>) { ) -> (f32, Vec<BlockLayout>) {
let editor = if let Some(editor) = self.view.upgrade(cx) {
editor
} else {
return Default::default();
};
let tooltip_style = cx.global::<Settings>().theme.tooltip.clone(); let tooltip_style = cx.global::<Settings>().theme.tooltip.clone();
let scroll_x = snapshot.scroll_anchor.offset.x(); let scroll_x = snapshot.scroll_anchor.offset.x();
let (fixed_blocks, non_fixed_blocks) = snapshot let (fixed_blocks, non_fixed_blocks) = snapshot
@ -1542,6 +1571,7 @@ impl EditorElement {
min: Vector2F::zero(), min: Vector2F::zero(),
max: vec2f(width, block.height() as f32 * line_height), max: vec2f(width, block.height() as f32 * line_height),
}, },
editor,
cx, cx,
); );
element element
@ -1847,6 +1877,7 @@ impl Element for EditorElement {
&style, &style,
&line_layouts, &line_layouts,
include_root, include_root,
editor,
cx, cx,
); );
@ -1924,6 +1955,7 @@ impl Element for EditorElement {
(12. * line_height).min((size.y() - line_height) / 2.), (12. * line_height).min((size.y() - line_height) / 2.),
), ),
}, },
editor,
cx, cx,
); );
} }
@ -1934,6 +1966,7 @@ impl Element for EditorElement {
Axis::Vertical, Axis::Vertical,
line_height * style.code_actions.vertical_scale, line_height * style.code_actions.vertical_scale,
), ),
editor,
cx, cx,
); );
} }
@ -2014,7 +2047,7 @@ impl Element for EditorElement {
cx: &mut PaintContext, cx: &mut PaintContext,
) -> Self::PaintState { ) -> Self::PaintState {
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
cx.scene.push_layer(Some(visible_bounds)); scene.push_layer(Some(visible_bounds));
let gutter_bounds = RectF::new(bounds.origin(), layout.gutter_size); let gutter_bounds = RectF::new(bounds.origin(), layout.gutter_size);
let text_bounds = RectF::new( let text_bounds = RectF::new(
@ -2033,20 +2066,20 @@ impl Element for EditorElement {
cx, cx,
); );
self.paint_background(gutter_bounds, text_bounds, layout, cx); self.paint_background(scene, gutter_bounds, text_bounds, layout, cx);
if layout.gutter_size.x() > 0. { if layout.gutter_size.x() > 0. {
self.paint_gutter(gutter_bounds, visible_bounds, layout, cx); self.paint_gutter(scene, gutter_bounds, visible_bounds, layout, editor, cx);
} }
self.paint_text(text_bounds, visible_bounds, layout, cx); self.paint_text(scene, text_bounds, visible_bounds, layout, editor, cx);
cx.scene.push_layer(Some(bounds)); scene.push_layer(Some(bounds));
if !layout.blocks.is_empty() { if !layout.blocks.is_empty() {
self.paint_blocks(bounds, visible_bounds, layout, cx); self.paint_blocks(scene, bounds, visible_bounds, layout, editor, cx);
} }
self.paint_scrollbar(bounds, layout, cx); self.paint_scrollbar(scene, bounds, layout, cx);
cx.scene.pop_layer(); scene.pop_layer();
cx.scene.pop_layer(); scene.pop_layer();
} }
fn rect_for_text_range( fn rect_for_text_range(
@ -2254,7 +2287,7 @@ impl Cursor {
) )
} }
pub fn paint(&self, origin: Vector2F, cx: &mut PaintContext) { pub fn paint(&self, scene: &mut SceneBuilder, origin: Vector2F, cx: &mut AppContext) {
let bounds = match self.shape { let bounds = match self.shape {
CursorShape::Bar => RectF::new(self.origin + origin, vec2f(2.0, self.line_height)), CursorShape::Bar => RectF::new(self.origin + origin, vec2f(2.0, self.line_height)),
CursorShape::Block | CursorShape::Hollow => RectF::new( CursorShape::Block | CursorShape::Hollow => RectF::new(
@ -2269,14 +2302,14 @@ impl Cursor {
//Draw background or border quad //Draw background or border quad
if matches!(self.shape, CursorShape::Hollow) { if matches!(self.shape, CursorShape::Hollow) {
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds, bounds,
background: None, background: None,
border: Border::all(1., self.color), border: Border::all(1., self.color),
corner_radius: 0., corner_radius: 0.,
}); });
} else { } else {
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds, bounds,
background: Some(self.color), background: Some(self.color),
border: Default::default(), border: Default::default(),
@ -2285,7 +2318,7 @@ impl Cursor {
} }
if let Some(block_text) = &self.block_text { if let Some(block_text) = &self.block_text {
block_text.paint(self.origin + origin, bounds, self.line_height, cx); block_text.paint(scene, self.origin + origin, bounds, self.line_height, cx);
} }
} }

View File

@ -4,7 +4,7 @@ use gpui::{
elements::{Flex, MouseEventHandler, Padding, Text}, elements::{Flex, MouseEventHandler, Padding, Text},
impl_internal_actions, impl_internal_actions,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
AppContext, Axis, Element, ElementBox, ModelHandle, RenderContext, Task, ViewContext, AppContext, Axis, Element, ElementBox, ModelHandle, Task, ViewContext,
}; };
use language::{Bias, DiagnosticEntry, DiagnosticSeverity}; use language::{Bias, DiagnosticEntry, DiagnosticSeverity};
use project::{HoverBlock, Project}; use project::{HoverBlock, Project};
@ -282,7 +282,7 @@ impl HoverState {
snapshot: &EditorSnapshot, snapshot: &EditorSnapshot,
style: &EditorStyle, style: &EditorStyle,
visible_rows: Range<u32>, visible_rows: Range<u32>,
cx: &mut RenderContext<Editor>, cx: &mut ViewContext<Editor>,
) -> Option<(DisplayPoint, Vec<ElementBox>)> { ) -> Option<(DisplayPoint, Vec<ElementBox>)> {
// If there is a diagnostic, position the popovers based on that. // If there is a diagnostic, position the popovers based on that.
// Otherwise use the start of the hover range // Otherwise use the start of the hover range
@ -323,7 +323,7 @@ pub struct InfoPopover {
} }
impl InfoPopover { impl InfoPopover {
pub fn render(&self, style: &EditorStyle, cx: &mut RenderContext<Editor>) -> ElementBox { pub fn render(&self, style: &EditorStyle, cx: &mut ViewContext<Editor>) -> ElementBox {
MouseEventHandler::<InfoPopover>::new(0, cx, |_, cx| { MouseEventHandler::<InfoPopover>::new(0, cx, |_, cx| {
let mut flex = Flex::new(Axis::Vertical).scrollable::<HoverBlock, _>(1, None, cx); let mut flex = Flex::new(Axis::Vertical).scrollable::<HoverBlock, _>(1, None, cx);
flex.extend(self.contents.iter().map(|content| { flex.extend(self.contents.iter().map(|content| {
@ -378,7 +378,7 @@ pub struct DiagnosticPopover {
} }
impl DiagnosticPopover { impl DiagnosticPopover {
pub fn render(&self, style: &EditorStyle, cx: &mut RenderContext<Editor>) -> ElementBox { pub fn render(&self, style: &EditorStyle, cx: &mut ViewContext<Editor>) -> ElementBox {
enum PrimaryDiagnostic {} enum PrimaryDiagnostic {}
let mut text_style = style.hover_popover.prose.clone(); let mut text_style = style.hover_popover.prose.clone();

View File

@ -7,8 +7,8 @@ use anyhow::{anyhow, Context, Result};
use collections::HashSet; use collections::HashSet;
use futures::future::try_join_all; use futures::future::try_join_all;
use gpui::{ use gpui::{
elements::*, geometry::vector::vec2f, AppContext, Entity, ModelHandle, RenderContext, elements::*, geometry::vector::vec2f, AppContext, Entity, ModelHandle, Subscription, Task,
Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, View, ViewContext, ViewContext, ViewHandle, WeakViewHandle,
}; };
use language::{ use language::{
proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, OffsetRangeExt, Point, proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, OffsetRangeExt, Point,
@ -1078,7 +1078,7 @@ impl View for CursorPosition {
"CursorPosition" "CursorPosition"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
if let Some(position) = self.position { if let Some(position) = self.position {
let theme = &cx.global::<Settings>().theme.workspace.status_bar; let theme = &cx.global::<Settings>().theme.workspace.status_bar;
let mut text = format!("{},{}", position.row + 1, position.column + 1); let mut text = format!("{},{}", position.row + 1, position.column + 1);

View File

@ -1,7 +1,7 @@
use gpui::{ use gpui::{
elements::*, elements::*,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
Entity, RenderContext, View, ViewContext, Entity, View, ViewContext,
}; };
use settings::Settings; use settings::Settings;
use workspace::{item::ItemHandle, StatusItemView}; use workspace::{item::ItemHandle, StatusItemView};
@ -27,7 +27,7 @@ impl View for DeployFeedbackButton {
"DeployFeedbackButton" "DeployFeedbackButton"
} }
fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> ElementBox {
let active = self.active; let active = self.active;
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
Stack::new() Stack::new()

View File

@ -12,8 +12,8 @@ use gpui::{
actions, actions,
elements::{ChildView, Flex, Label, ParentElement, Svg}, elements::{ChildView, Flex, Label, ParentElement, Svg},
platform::PromptLevel, platform::PromptLevel,
serde_json, AnyViewHandle, AppContext, Element, ElementBox, Entity, ModelHandle, RenderContext, serde_json, AnyViewHandle, AppContext, Element, ElementBox, Entity, ModelHandle, Task, View,
Task, View, ViewContext, ViewHandle, ViewContext, ViewContext, ViewHandle,
}; };
use isahc::Request; use isahc::Request;
use language::Buffer; use language::Buffer;
@ -232,7 +232,7 @@ impl View for FeedbackEditor {
"FeedbackEditor" "FeedbackEditor"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
ChildView::new(&self.editor, cx).boxed() ChildView::new(&self.editor, cx).boxed()
} }

View File

@ -1,7 +1,7 @@
use gpui::{ use gpui::{
elements::{Flex, Label, MouseEventHandler, ParentElement, Text}, elements::{Flex, Label, MouseEventHandler, ParentElement, Text},
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
Element, ElementBox, Entity, RenderContext, View, ViewContext, ViewHandle, Element, ElementBox, Entity, View, ViewContext, ViewHandle,
}; };
use settings::Settings; use settings::Settings;
use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView}; use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView};
@ -29,7 +29,7 @@ impl View for FeedbackInfoText {
"FeedbackInfoText" "FeedbackInfoText"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
Flex::row() Flex::row()

View File

@ -1,7 +1,7 @@
use gpui::{ use gpui::{
elements::{Label, MouseEventHandler}, elements::{Label, MouseEventHandler},
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
Element, ElementBox, Entity, RenderContext, View, ViewContext, ViewHandle, Element, ElementBox, Entity, View, ViewContext, ViewHandle,
}; };
use settings::Settings; use settings::Settings;
use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView}; use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView};
@ -29,7 +29,7 @@ impl View for SubmitFeedbackButton {
"SubmitFeedbackButton" "SubmitFeedbackButton"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
enum SubmitFeedbackButton {} enum SubmitFeedbackButton {}
MouseEventHandler::<SubmitFeedbackButton>::new(0, cx, |state, _| { MouseEventHandler::<SubmitFeedbackButton>::new(0, cx, |state, _| {

View File

@ -1,7 +1,7 @@
use fuzzy::PathMatch; use fuzzy::PathMatch;
use gpui::{ use gpui::{
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, Task, View,
RenderContext, Task, View, ViewContext, ViewHandle, ViewContext, ViewHandle,
}; };
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId}; use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
@ -50,7 +50,7 @@ impl View for FileFinder {
"FileFinder" "FileFinder"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
ChildView::new(&self.picker, cx).boxed() ChildView::new(&self.picker, cx).boxed()
} }

View File

@ -3,7 +3,7 @@ use std::sync::Arc;
use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, DisplayPoint, Editor}; use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, DisplayPoint, Editor};
use gpui::{ use gpui::{
actions, elements::*, geometry::vector::Vector2F, AnyViewHandle, AppContext, Axis, Entity, actions, elements::*, geometry::vector::Vector2F, AnyViewHandle, AppContext, Axis, Entity,
RenderContext, View, ViewContext, ViewHandle, View, ViewContext, ViewHandle,
}; };
use menu::{Cancel, Confirm}; use menu::{Cancel, Confirm};
use settings::Settings; use settings::Settings;
@ -156,7 +156,7 @@ impl View for GoToLine {
"GoToLine" "GoToLine"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = &cx.global::<Settings>().theme.picker; let theme = &cx.global::<Settings>().theme.picker;
let label = format!( let label = format!(

View File

@ -2,7 +2,7 @@ use gpui::{
color::Color, color::Color,
fonts::{Properties, Weight}, fonts::{Properties, Weight},
text_layout::RunStyle, text_layout::RunStyle,
DebugContext, Element as _, MeasurementContext, Quad, Element, ElementBox, Quad, SceneBuilder, View, ViewContext,
}; };
use log::LevelFilter; use log::LevelFilter;
use pathfinder_geometry::rect::RectF; use pathfinder_geometry::rect::RectF;
@ -30,12 +30,12 @@ impl gpui::View for TextView {
"View" "View"
} }
fn render(&mut self, _: &mut gpui::RenderContext<Self>) -> gpui::ElementBox { fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> ElementBox<TextView> {
TextElement.boxed() TextElement.boxed()
} }
} }
impl gpui::Element for TextElement { impl<V: View> Element<V> for TextElement {
type LayoutState = (); type LayoutState = ();
type PaintState = (); type PaintState = ();
@ -43,17 +43,20 @@ impl gpui::Element for TextElement {
fn layout( fn layout(
&mut self, &mut self,
constraint: gpui::SizeConstraint, constraint: gpui::SizeConstraint,
_: &mut gpui::LayoutContext, _: &mut V,
_: &mut ViewContext<V>,
) -> (pathfinder_geometry::vector::Vector2F, Self::LayoutState) { ) -> (pathfinder_geometry::vector::Vector2F, Self::LayoutState) {
(constraint.max, ()) (constraint.max, ())
} }
fn paint( fn paint(
&mut self, &mut self,
scene: &mut SceneBuilder,
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
_: &mut Self::LayoutState, _: &mut Self::LayoutState,
cx: &mut gpui::PaintContext, _: &mut V,
cx: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
let font_size = 12.; let font_size = 12.;
let family = cx let family = cx
@ -84,7 +87,7 @@ impl gpui::Element for TextElement {
}; };
let text = "Hello world!"; let text = "Hello world!";
let line = cx.text_layout_cache.layout_str( let line = cx.text_layout_cache().layout_str(
text, text,
font_size, font_size,
&[ &[
@ -96,12 +99,12 @@ impl gpui::Element for TextElement {
], ],
); );
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds, bounds,
background: Some(Color::white()), background: Some(Color::white()),
..Default::default() ..Default::default()
}); });
line.paint(bounds.origin(), visible_bounds, bounds.height(), cx); line.paint(scene, bounds.origin(), visible_bounds, bounds.height(), cx);
} }
fn rect_for_text_range( fn rect_for_text_range(
@ -111,7 +114,8 @@ impl gpui::Element for TextElement {
_: RectF, _: RectF,
_: &Self::LayoutState, _: &Self::LayoutState,
_: &Self::PaintState, _: &Self::PaintState,
_: &MeasurementContext, _: &V,
_: &ViewContext<V>,
) -> Option<RectF> { ) -> Option<RectF> {
None None
} }
@ -121,7 +125,8 @@ impl gpui::Element for TextElement {
_: RectF, _: RectF,
_: &Self::LayoutState, _: &Self::LayoutState,
_: &Self::PaintState, _: &Self::PaintState,
_: &DebugContext, _: &V,
_: &ViewContext<V>,
) -> gpui::json::Value { ) -> gpui::json::Value {
todo!() todo!()
} }

View File

@ -69,7 +69,7 @@ pub trait Entity: 'static {
pub trait View: Entity + Sized { pub trait View: Entity + Sized {
fn ui_name() -> &'static str; fn ui_name() -> &'static str;
fn render(&mut self, cx: &mut ViewContext<'_, '_, Self>) -> ElementBox<Self>; fn render(&mut self, cx: &mut ViewContext<'_, '_, '_, Self>) -> ElementBox<Self>;
fn focus_in(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {} fn focus_in(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {} fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
fn key_down(&mut self, _: &KeyDownEvent, _: &mut ViewContext<Self>) -> bool { fn key_down(&mut self, _: &KeyDownEvent, _: &mut ViewContext<Self>) -> bool {
@ -488,7 +488,7 @@ impl ReadViewWith for AsyncAppContext {
} }
} }
type ActionCallback = dyn FnMut(&mut dyn AnyView, &dyn Action, &mut AppContext, usize, usize); type ActionCallback = dyn FnMut(&mut dyn AnyView, &dyn Action, &mut WindowContext, usize);
type GlobalActionCallback = dyn FnMut(&dyn Action, &mut AppContext); type GlobalActionCallback = dyn FnMut(&dyn Action, &mut AppContext);
type SubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut AppContext) -> bool>; type SubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut AppContext) -> bool>;
@ -725,11 +725,10 @@ impl AppContext {
let handler = Box::new( let handler = Box::new(
move |view: &mut dyn AnyView, move |view: &mut dyn AnyView,
action: &dyn Action, action: &dyn Action,
cx: &mut AppContext, cx: &mut WindowContext,
window_id: usize,
view_id: usize| { view_id: usize| {
let action = action.as_any().downcast_ref().unwrap(); let action = action.as_any().downcast_ref().unwrap();
let mut cx = ViewContext::new(cx, view_id); let mut cx = ViewContext::mutable(cx, view_id);
handler( handler(
view.as_any_mut() view.as_any_mut()
.downcast_mut() .downcast_mut()
@ -842,6 +841,12 @@ impl AppContext {
} }
} }
fn focused_view_id(&self, window_id: usize) -> Option<usize> {
self.windows
.get(&window_id)
.and_then(|window| window.focused_view_id)
}
pub fn is_child_focused(&self, view: &AnyViewHandle) -> bool { pub fn is_child_focused(&self, view: &AnyViewHandle) -> bool {
if let Some(focused_view_id) = self.focused_view_id(view.window_id) { if let Some(focused_view_id) = self.focused_view_id(view.window_id) {
self.ancestors(view.window_id, focused_view_id) self.ancestors(view.window_id, focused_view_id)
@ -858,7 +863,8 @@ impl AppContext {
self.active_labeled_tasks.values().cloned() self.active_labeled_tasks.values().cloned()
} }
// pub fn render_view(&mut self, params: RenderParams) -> Result<ElementBox<Self>> { pub fn render_view(&mut self, params: RenderParams) -> Result<Box<dyn RenderedView>> {
todo!()
// let window_id = params.window_id; // let window_id = params.window_id;
// let view_id = params.view_id; // let view_id = params.view_id;
// let mut view = self // let mut view = self
@ -868,14 +874,15 @@ impl AppContext {
// let element = view.render(params, self); // let element = view.render(params, self);
// self.views.insert((window_id, view_id), view); // self.views.insert((window_id, view_id), view);
// Ok(element) // Ok(element)
// } }
// pub fn render_views( pub fn render_views(
// &mut self, &mut self,
// window_id: usize, window_id: usize,
// titlebar_height: f32, titlebar_height: f32,
// appearance: Appearance, appearance: Appearance,
// ) -> HashMap<usize, ElementBox> { ) -> HashMap<usize, Box<dyn RenderedView>> {
todo!()
// self.start_frame(); // self.start_frame();
// #[allow(clippy::needless_collect)] // #[allow(clippy::needless_collect)]
// let view_ids = self // let view_ids = self
@ -908,7 +915,7 @@ impl AppContext {
// ) // )
// }) // })
// .collect() // .collect()
// } }
pub(crate) fn start_frame(&mut self) { pub(crate) fn start_frame(&mut self) {
self.frame_count += 1; self.frame_count += 1;
@ -932,6 +939,7 @@ impl AppContext {
app_context, app_context,
window: &mut window, window: &mut window,
window_id, window_id,
refreshing: false,
}; };
let result = callback(&mut window_context); let result = callback(&mut window_context);
@ -1510,25 +1518,22 @@ impl AppContext {
}) })
} }
pub fn add_window<T, F>( pub fn add_window<V, F>(
&mut self, &mut self,
window_options: WindowOptions, window_options: WindowOptions,
build_root_view: F, build_root_view: F,
) -> (usize, ViewHandle<T>) ) -> (usize, ViewHandle<V>)
where where
T: View, V: View,
F: FnOnce(&mut ViewContext<T>) -> T, F: FnOnce(&mut ViewContext<V>) -> V,
{ {
self.update(|this| { self.update(|this| {
let window_id = post_inc(&mut this.next_window_id); let window_id = post_inc(&mut this.next_window_id);
let root_view = this
.build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx)))
.unwrap();
let platform_window = let platform_window =
this.platform this.platform
.open_window(window_id, window_options, this.foreground.clone()); .open_window(window_id, window_options, this.foreground.clone());
let window = let window = this.build_window(window_id, platform_window, build_root_view);
this.build_window(window_id, root_view.clone().into_any(), platform_window); let root_view = window.root_view().clone().downcast::<V>().unwrap();
this.windows.insert(window_id, window); this.windows.insert(window_id, window);
root_view.update(this, |view, cx| view.focus_in(cx.handle().into_any(), cx)); root_view.update(this, |view, cx| view.focus_in(cx.handle().into_any(), cx));
@ -1537,20 +1542,16 @@ impl AppContext {
}) })
} }
pub fn add_status_bar_item<T, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<T>) pub fn add_status_bar_item<V, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<V>)
where where
T: View, V: View,
F: FnOnce(&mut ViewContext<T>) -> T, F: FnOnce(&mut ViewContext<V>) -> V,
{ {
self.update(|this| { self.update(|this| {
let window_id = post_inc(&mut this.next_window_id); let window_id = post_inc(&mut this.next_window_id);
let root_view = this
.build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx)))
.unwrap();
let platform_window = this.platform.add_status_item(); let platform_window = this.platform.add_status_item();
let window = let window = this.build_window(window_id, platform_window, build_root_view);
this.build_window(window_id, root_view.clone().into_any(), platform_window); let root_view = window.root_view().clone().downcast::<V>().unwrap();
this.windows.insert(window_id, window); this.windows.insert(window_id, window);
root_view.update(this, |view, cx| view.focus_in(cx.handle().into_any(), cx)); root_view.update(this, |view, cx| view.focus_in(cx.handle().into_any(), cx));
@ -1563,33 +1564,21 @@ impl AppContext {
self.remove_window(id); self.remove_window(id);
} }
pub fn replace_root_view<T, F>(&mut self, window_id: usize, build_root_view: F) -> ViewHandle<T>
where
T: View,
F: FnOnce(&mut ViewContext<T>) -> T,
{
self.update(|this| {
let root_view = this
.build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx)))
.unwrap();
let window = this.windows.get_mut(&window_id).unwrap();
window.root_view = root_view.clone().into_any();
window.focused_view_id = Some(root_view.id());
root_view
})
}
pub fn remove_window(&mut self, window_id: usize) { pub fn remove_window(&mut self, window_id: usize) {
self.windows.remove(&window_id); self.windows.remove(&window_id);
self.flush_effects(); self.flush_effects();
} }
pub fn build_window( pub fn build_window<V, F>(
&mut self, &mut self,
window_id: usize, window_id: usize,
root_view: AnyViewHandle,
mut platform_window: Box<dyn platform::Window>, mut platform_window: Box<dyn platform::Window>,
) -> Window { build_root_view: F,
) -> Window
where
V: View,
F: FnOnce(&mut ViewContext<V>) -> V,
{
{ {
let mut app = self.upgrade(); let mut app = self.upgrade();
@ -1653,73 +1642,22 @@ impl AppContext {
window_id, window_id,
})); }));
let mut window = Window::new(window_id, root_view, platform_window, self); let mut window = Window::new(window_id, platform_window, self, build_root_view);
let scene = WindowContext::new(self, &mut window, window_id).build_scene(); let scene = WindowContext::new(self, &mut window, window_id).build_scene();
window.platform_window.present_scene(scene); window.platform_window.present_scene(scene);
window window
} }
pub fn add_view<T, F>(&mut self, parent_handle: &AnyViewHandle, build_view: F) -> ViewHandle<T> pub fn add_view<S, F>(&mut self, parent: &AnyViewHandle, build_view: F) -> ViewHandle<S>
where where
T: View, S: View,
F: FnOnce(&mut ViewContext<T>) -> T, F: FnOnce(&mut ViewContext<S>) -> S,
{ {
self.build_and_insert_view( self.update_window(parent.window_id, |cx| {
parent_handle.window_id, cx.build_and_insert_view(ParentId::View(parent.view_id), |cx| Some(build_view(cx)))
ParentId::View(parent_handle.view_id),
|cx| Some(build_view(cx)),
)
.unwrap() .unwrap()
}
pub fn add_option_view<T, F>(
&mut self,
parent_handle: impl Into<AnyViewHandle>,
build_view: F,
) -> Option<ViewHandle<T>>
where
T: View,
F: FnOnce(&mut ViewContext<T>) -> Option<T>,
{
let parent_handle = parent_handle.into();
self.build_and_insert_view(
parent_handle.window_id,
ParentId::View(parent_handle.view_id),
build_view,
)
}
pub(crate) fn build_and_insert_view<T, F>(
&mut self,
window_id: usize,
parent_id: ParentId,
build_view: F,
) -> Option<ViewHandle<T>>
where
T: View,
F: FnOnce(&mut ViewContext<T>) -> Option<T>,
{
self.update(|this| {
let view_id = post_inc(&mut this.next_entity_id);
// Make sure we can tell child views about their parent
this.parents.insert((window_id, view_id), parent_id);
let mut cx = ViewContext::new(this, view_id);
let handle = if let Some(view) = build_view(&mut cx) {
this.views.insert((window_id, view_id), Box::new(view));
if let Some(window) = this.windows.get_mut(&window_id) {
window
.invalidation
.get_or_insert_with(Default::default)
.updated
.insert(view_id);
}
Some(ViewHandle::new(window_id, view_id, &this.ref_counts))
} else {
this.parents.remove(&(window_id, view_id));
None
};
handle
}) })
.unwrap()
} }
fn remove_dropped_entities(&mut self) { fn remove_dropped_entities(&mut self) {
@ -1754,7 +1692,7 @@ impl AppContext {
.removed .removed
.push(view_id); .push(view_id);
if window.focused_view_id == Some(view_id) { if window.focused_view_id == Some(view_id) {
Some(window.root_view.id()) Some(window.root_view().id())
} else { } else {
None None
} }
@ -2174,7 +2112,10 @@ impl AppContext {
self.update(|cx| { self.update(|cx| {
cx.update_window(window_id, |cx| { cx.update_window(window_id, |cx| {
let focused_id = cx.window.focused_view_id?; let Some(focused_id) = cx.window.focused_view_id else {
return;
};
for view_id in cx.ancestors(window_id, focused_id).collect::<Vec<_>>() { for view_id in cx.ancestors(window_id, focused_id).collect::<Vec<_>>() {
cx.update_any_view(focused_id, |view, cx| { cx.update_any_view(focused_id, |view, cx| {
if active { if active {
@ -2254,29 +2195,28 @@ impl AppContext {
if let Some(view_id) = view_id { if let Some(view_id) = view_id {
this.halt_action_dispatch = false; this.halt_action_dispatch = false;
this.visit_dispatch_path(window_id, view_id, |view_id, capture_phase, this| { this.visit_dispatch_path(window_id, view_id, |view_id, capture_phase, this| {
if let Some(mut view) = this.views.remove(&(window_id, view_id)) { this.update_window(window_id, |cx| {
cx.update_any_view(view_id, |view, cx| {
let type_id = view.as_any().type_id(); let type_id = view.as_any().type_id();
if let Some((name, mut handlers)) = cx
if let Some((name, mut handlers)) = this
.actions_mut(capture_phase) .actions_mut(capture_phase)
.get_mut(&type_id) .get_mut(&type_id)
.and_then(|h| h.remove_entry(&action.id())) .and_then(|h| h.remove_entry(&action.id()))
{ {
for handler in handlers.iter_mut().rev() { for handler in handlers.iter_mut().rev() {
this.halt_action_dispatch = true; cx.halt_action_dispatch = true;
handler(view.as_mut(), action, this, window_id, view_id); handler(view, action, cx, view_id);
if this.halt_action_dispatch { if cx.halt_action_dispatch {
break; break;
} }
} }
this.actions_mut(capture_phase) cx.actions_mut(capture_phase)
.get_mut(&type_id) .get_mut(&type_id)
.unwrap() .unwrap()
.insert(name, handlers); .insert(name, handlers);
} }
})
this.views.insert((window_id, view_id), view); });
}
!this.halt_action_dispatch !this.halt_action_dispatch
}); });
@ -2523,22 +2463,19 @@ impl UpdateView for AppContext {
where where
T: View, T: View,
{ {
self.update(|this| { self.update_window(handle.window_id, |cx| {
let mut view = this cx.update_any_view(handle.view_id, |view, cx| {
.views let mut cx = ViewContext::mutable(cx, handle.view_id);
.remove(&(handle.window_id, handle.view_id)) update(
.expect("circular view update");
let mut cx = ViewContext::new(this, handle.view_id);
let result = update(
view.as_any_mut() view.as_any_mut()
.downcast_mut() .downcast_mut()
.expect("downcast is type safe"), .expect("downcast is type safe"),
&mut cx, &mut cx,
); )
this.views.insert((handle.window_id, handle.view_id), view);
result
}) })
.unwrap() // TODO: Are these unwraps safe?
})
.unwrap()
} }
} }
@ -2877,68 +2814,42 @@ pub trait AnyView {
cx: &mut AppContext, cx: &mut AppContext,
) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>; ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
fn ui_name(&self) -> &'static str; fn ui_name(&self) -> &'static str;
fn render<'a, 'b>( fn render(&mut self, params: RenderParams, cx: &mut WindowContext) -> Box<dyn RenderedView>;
&mut self,
params: RenderParams,
cx: &'b mut WindowContext<'a, 'b>,
) -> Box<dyn RenderedView>;
fn focus_in<'a, 'b>( fn focus_in<'a, 'b>(
&mut self, &mut self,
focused_id: usize, focused_id: usize,
cx: &'b mut WindowContext<'a, 'b>, cx: &mut WindowContext<'a, 'b>,
view_id: usize, view_id: usize,
); );
fn focus_out<'a, 'b>( fn focus_out(&mut self, focused_id: usize, cx: &mut WindowContext, view_id: usize);
&mut self, fn key_down(&mut self, event: &KeyDownEvent, cx: &mut WindowContext, view_id: usize) -> bool;
focused_id: usize, fn key_up(&mut self, event: &KeyUpEvent, cx: &mut WindowContext, view_id: usize) -> bool;
cx: &'b mut WindowContext<'a, 'b>, fn modifiers_changed(
view_id: usize,
);
fn key_down<'a, 'b>(
&mut self,
event: &KeyDownEvent,
cx: &'b mut WindowContext<'a, 'b>,
view_id: usize,
) -> bool;
fn key_up<'a, 'b>(
&mut self,
event: &KeyUpEvent,
cx: &'b mut WindowContext<'a, 'b>,
view_id: usize,
) -> bool;
fn modifiers_changed<'a, 'b>(
&mut self, &mut self,
event: &ModifiersChangedEvent, event: &ModifiersChangedEvent,
cx: &'b mut WindowContext<'a, 'b>, cx: &mut WindowContext,
view_id: usize, view_id: usize,
) -> bool; ) -> bool;
fn keymap_context<'a, 'b>(&self, cx: &'b mut WindowContext<'a, 'b>) -> KeymapContext; fn keymap_context(&self, cx: &AppContext) -> KeymapContext;
fn debug_json<'a, 'b>(&self, cx: &'b WindowContext<'a, 'b>) -> serde_json::Value; fn debug_json(&self, cx: &WindowContext) -> serde_json::Value;
fn text_for_range<'a, 'b>( fn text_for_range(&self, range: Range<usize>, cx: &WindowContext) -> Option<String>;
&self, fn selected_text_range(&self, cx: &WindowContext) -> Option<Range<usize>>;
range: Range<usize>, fn marked_text_range(&self, cx: &WindowContext) -> Option<Range<usize>>;
cx: &'b mut WindowContext<'a, 'b>, fn unmark_text(&mut self, cx: &mut WindowContext, view_id: usize);
) -> Option<String>; fn replace_text_in_range(
fn selected_text_range<'a, 'b>(
&self,
cx: &'b mut WindowContext<'a, 'b>,
) -> Option<Range<usize>>;
fn marked_text_range<'a, 'b>(&self, cx: &'b mut WindowContext<'a, 'b>) -> Option<Range<usize>>;
fn unmark_text<'a, 'b>(&mut self, cx: &'b mut WindowContext<'a, 'b>, view_id: usize);
fn replace_text_in_range<'a, 'b>(
&mut self, &mut self,
range: Option<Range<usize>>, range: Option<Range<usize>>,
text: &str, text: &str,
cx: &'b mut WindowContext<'a, 'b>, cx: &mut WindowContext,
view_id: usize, view_id: usize,
); );
fn replace_and_mark_text_in_range<'a, 'b>( fn replace_and_mark_text_in_range(
&mut self, &mut self,
range: Option<Range<usize>>, range: Option<Range<usize>>,
new_text: &str, new_text: &str,
new_selected_range: Option<Range<usize>>, new_selected_range: Option<Range<usize>>,
cx: &'b mut WindowContext<'a, 'b>, cx: &mut WindowContext,
view_id: usize, view_id: usize,
); );
fn any_handle(&self, window_id: usize, view_id: usize, cx: &AppContext) -> AnyViewHandle { fn any_handle(&self, window_id: usize, view_id: usize, cx: &AppContext) -> AnyViewHandle {
@ -2978,21 +2889,13 @@ where
T::ui_name() T::ui_name()
} }
fn render<'a, 'b>( fn render(&mut self, params: RenderParams, cx: &mut WindowContext) -> Box<dyn RenderedView> {
&mut self, todo!()
params: RenderParams, // Box::new(View::render(self, &mut ViewContext::new(params.view_id, cx)))
cx: &mut WindowContext<'a, 'b>,
) -> Box<dyn RenderedView> {
View::render(self, &mut ViewContext::new(params, cx))
} }
fn focus_in<'a, 'b>( fn focus_in(&mut self, focused_id: usize, cx: &mut WindowContext, view_id: usize) {
&mut self, let mut cx = ViewContext::mutable(cx, view_id);
cx: &mut WindowContext<'a, 'b>,
view_id: usize,
focused_id: usize,
) {
let mut cx = ViewContext::new(cx, view_id);
let focused_view_handle: AnyViewHandle = if view_id == focused_id { let focused_view_handle: AnyViewHandle = if view_id == focused_id {
cx.handle().into_any() cx.handle().into_any()
} else { } else {
@ -3012,13 +2915,8 @@ where
View::focus_in(self, focused_view_handle, &mut cx); View::focus_in(self, focused_view_handle, &mut cx);
} }
fn focus_out<'a, 'b>( fn focus_out(&mut self, blurred_id: usize, cx: &mut WindowContext, view_id: usize) {
&mut self, let mut cx = ViewContext::mutable(cx, view_id);
cx: &mut WindowContext<'a, 'b>,
view_id: usize,
blurred_id: usize,
) {
let mut cx = ViewContext::new(cx, view_id);
let blurred_view_handle: AnyViewHandle = if view_id == blurred_id { let blurred_view_handle: AnyViewHandle = if view_id == blurred_id {
cx.handle().into_any() cx.handle().into_any()
} else { } else {
@ -3038,85 +2936,71 @@ where
View::focus_out(self, blurred_view_handle, &mut cx); View::focus_out(self, blurred_view_handle, &mut cx);
} }
fn key_down<'a, 'b>( fn key_down(&mut self, event: &KeyDownEvent, cx: &mut WindowContext, view_id: usize) -> bool {
&mut self, let mut cx = ViewContext::mutable(cx, view_id);
event: &KeyDownEvent,
cx: &mut WindowContext<'a, 'b>,
view_id: usize,
) -> bool {
let mut cx = ViewContext::new(cx, view_id);
View::key_down(self, event, &mut cx) View::key_down(self, event, &mut cx)
} }
fn key_up<'a, 'b>( fn key_up(&mut self, event: &KeyUpEvent, cx: &mut WindowContext, view_id: usize) -> bool {
&mut self, let mut cx = ViewContext::mutable(cx, view_id);
event: &KeyUpEvent,
cx: &mut WindowContext<'a, 'b>,
view_id: usize,
) -> bool {
let mut cx = ViewContext::new(cx, view_id);
View::key_up(self, event, &mut cx) View::key_up(self, event, &mut cx)
} }
fn modifiers_changed<'a, 'b>( fn modifiers_changed(
&mut self, &mut self,
event: &ModifiersChangedEvent, event: &ModifiersChangedEvent,
cx: &mut WindowContext<'a, 'b>, cx: &mut WindowContext,
view_id: usize, view_id: usize,
) -> bool { ) -> bool {
let mut cx = ViewContext::new(cx, view_id); let mut cx = ViewContext::mutable(cx, view_id);
View::modifiers_changed(self, event, &mut cx) View::modifiers_changed(self, event, &mut cx)
} }
fn keymap_context<'a, 'b>(&self, cx: &mut WindowContext<'a, 'b>) -> KeymapContext { fn keymap_context(&self, cx: &AppContext) -> KeymapContext {
View::keymap_context(self, cx) View::keymap_context(self, cx)
} }
fn debug_json<'a, 'b>(&self, cx: &mut WindowContext<'a, 'b>) -> serde_json::Value { fn debug_json(&self, cx: &WindowContext) -> serde_json::Value {
View::debug_json(self, cx) View::debug_json(self, cx)
} }
fn text_for_range<'a, 'b>( fn text_for_range(&self, range: Range<usize>, cx: &WindowContext) -> Option<String> {
&self,
range: Range<usize>,
cx: &mut WindowContext<'a, 'b>,
) -> Option<String> {
View::text_for_range(self, range, cx) View::text_for_range(self, range, cx)
} }
fn selected_text_range<'a, 'b>(&self, cx: &mut WindowContext<'a, 'b>) -> Option<Range<usize>> { fn selected_text_range(&self, cx: &WindowContext) -> Option<Range<usize>> {
View::selected_text_range(self, cx) View::selected_text_range(self, cx)
} }
fn marked_text_range<'a, 'b>(&self, cx: &mut WindowContext<'a, 'b>) -> Option<Range<usize>> { fn marked_text_range(&self, cx: &WindowContext) -> Option<Range<usize>> {
View::marked_text_range(self, cx) View::marked_text_range(self, cx)
} }
fn unmark_text<'a, 'b>(&mut self, cx: &mut WindowContext<'a, 'b>, view_id: usize) { fn unmark_text(&mut self, cx: &mut WindowContext, view_id: usize) {
let mut cx = ViewContext::new(cx, view_id); let mut cx = ViewContext::mutable(cx, view_id);
View::unmark_text(self, &mut cx) View::unmark_text(self, &mut cx)
} }
fn replace_text_in_range<'a, 'b>( fn replace_text_in_range(
&mut self, &mut self,
range: Option<Range<usize>>, range: Option<Range<usize>>,
text: &str, text: &str,
cx: &mut WindowContext<'a, 'b>, cx: &mut WindowContext,
view_id: usize, view_id: usize,
) { ) {
let mut cx = ViewContext::new(cx, view_id); let mut cx = ViewContext::mutable(cx, view_id);
View::replace_text_in_range(self, range, text, &mut cx) View::replace_text_in_range(self, range, text, &mut cx)
} }
fn replace_and_mark_text_in_range<'a, 'b>( fn replace_and_mark_text_in_range(
&mut self, &mut self,
range: Option<Range<usize>>, range: Option<Range<usize>>,
new_text: &str, new_text: &str,
new_selected_range: Option<Range<usize>>, new_selected_range: Option<Range<usize>>,
cx: &mut WindowContext<'a, 'b>, cx: &mut WindowContext,
view_id: usize, view_id: usize,
) { ) {
let mut cx = ViewContext::new(cx, view_id); let mut cx = ViewContext::mutable(cx, view_id);
View::replace_and_mark_text_in_range(self, range, new_text, new_selected_range, &mut cx) View::replace_and_mark_text_in_range(self, range, new_text, new_selected_range, &mut cx)
} }
} }
@ -3339,13 +3223,13 @@ impl<M> DerefMut for ModelContext<'_, M> {
} }
} }
pub struct ViewContext<'a, 'b, T: ?Sized> { pub struct ViewContext<'a, 'b, 'c, T: ?Sized> {
window_context: WindowContext<'a, 'b>, window_context: WindowContextRef<'a, 'b, 'c>,
view_id: usize, view_id: usize,
view_type: PhantomData<T>, view_type: PhantomData<T>,
} }
impl<'a, 'b, T: View> Deref for ViewContext<'a, 'b, T> { impl<'a, 'b, 'c, T: View> Deref for ViewContext<'a, 'b, 'c, T> {
type Target = WindowContext<'a, 'b>; type Target = WindowContext<'a, 'b>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
@ -3353,16 +3237,24 @@ impl<'a, 'b, T: View> Deref for ViewContext<'a, 'b, T> {
} }
} }
impl<'a, 'b, T: View> DerefMut for ViewContext<'a, 'b, T> { impl<T: View> DerefMut for ViewContext<'_, '_, '_, T> {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.window_context &mut self.window_context
} }
} }
impl<'a, 'b, V: View> ViewContext<'a, 'b, V> { impl<'a, 'b, 'c, V: View> ViewContext<'a, 'b, 'c, V> {
fn new(window_context: &'b mut WindowContext<'a, 'b>, view_id: usize) -> Self { pub(crate) fn mutable(window_context: &'c mut WindowContext<'a, 'b>, view_id: usize) -> Self {
Self { Self {
window_context, window_context: WindowContextRef::Mutable(window_context),
view_id,
view_type: PhantomData,
}
}
pub(crate) fn immutable(window_context: &'c WindowContext<'a, 'b>, view_id: usize) -> Self {
Self {
window_context: WindowContextRef::Immutable(window_context),
view_id, view_id,
view_type: PhantomData, view_type: PhantomData,
} }
@ -3425,12 +3317,13 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
} }
pub fn focus_self(&mut self) { pub fn focus_self(&mut self) {
self.window_context let window_id = self.window_id;
.focus(self.window_id, Some(self.view_id)); let view_id = self.view_id;
self.window_context.focus(window_id, Some(view_id));
} }
pub fn is_self_focused(&self) -> bool { pub fn is_self_focused(&self) -> bool {
self.window.focused_view == Some(self.view_id) self.window.focused_view_id == Some(self.view_id)
} }
pub fn is_child(&self, view: impl Into<AnyViewHandle>) -> bool { pub fn is_child(&self, view: impl Into<AnyViewHandle>) -> bool {
@ -3444,7 +3337,8 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
} }
pub fn blur(&mut self) { pub fn blur(&mut self) {
self.window_context.focus(self.window_id, None); let window_id = self.window_id;
self.window_context.focus(window_id, None);
} }
pub fn on_window_should_close<F>(&mut self, mut callback: F) pub fn on_window_should_close<F>(&mut self, mut callback: F)
@ -3466,23 +3360,13 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
}); });
} }
pub fn add_model<S, F>(&mut self, build_model: F) -> ModelHandle<S>
where
S: Entity,
F: FnOnce(&mut ModelContext<S>) -> S,
{
self.window_context.add_model(build_model)
}
pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S> pub fn add_view<S, F>(&mut self, build_view: F) -> ViewHandle<S>
where where
S: View, S: View,
F: FnOnce(&mut ViewContext<S>) -> S, F: FnOnce(&mut ViewContext<S>) -> S,
{ {
self.window_context self.window_context
.build_and_insert_view(self.window_id, ParentId::View(self.view_id), |cx| { .build_and_insert_view(ParentId::View(self.view_id), |cx| Some(build_view(cx)))
Some(build_view(cx))
})
.unwrap() .unwrap()
} }
@ -3491,11 +3375,8 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
S: View, S: View,
F: FnOnce(&mut ViewContext<S>) -> Option<S>, F: FnOnce(&mut ViewContext<S>) -> Option<S>,
{ {
self.window_context.build_and_insert_view( self.window_context
self.window_id, .build_and_insert_view(ParentId::View(self.view_id), build_view)
ParentId::View(self.view_id),
build_view,
)
} }
pub fn reparent(&mut self, view_handle: &AnyViewHandle) { pub fn reparent(&mut self, view_handle: &AnyViewHandle) {
@ -3511,23 +3392,6 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
); );
} }
pub fn replace_root_view<W, F>(&mut self, build_root_view: F) -> ViewHandle<W>
where
W: View,
F: FnOnce(&mut ViewContext<W>) -> W,
{
let window_id = self.window_id;
self.update(|this| {
let root_view = this
.build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx)))
.unwrap();
let window = this.windows.get_mut(&window_id).unwrap();
window.root_view = root_view.clone().into_any();
window.focused_view_id = Some(root_view.id());
root_view
})
}
pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription pub fn subscribe<E, H, F>(&mut self, handle: &H, mut callback: F) -> Subscription
where where
E: Entity, E: Entity,
@ -3637,8 +3501,9 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
F: 'static + FnMut(&mut V, bool, &mut ViewContext<V>), F: 'static + FnMut(&mut V, bool, &mut ViewContext<V>),
{ {
let observer = self.weak_handle(); let observer = self.weak_handle();
let window_id = self.window_id;
self.window_context self.window_context
.observe_window_activation(self.window_id(), move |active, cx| { .observe_window_activation(window_id, move |active, cx| {
if let Some(observer) = observer.upgrade(cx) { if let Some(observer) = observer.upgrade(cx) {
observer.update(cx, |observer, cx| { observer.update(cx, |observer, cx| {
callback(observer, active, cx); callback(observer, active, cx);
@ -3655,8 +3520,9 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
F: 'static + FnMut(&mut V, bool, &mut ViewContext<V>), F: 'static + FnMut(&mut V, bool, &mut ViewContext<V>),
{ {
let observer = self.weak_handle(); let observer = self.weak_handle();
let window_id = self.window_id;
self.window_context self.window_context
.observe_fullscreen(self.window_id(), move |active, cx| { .observe_fullscreen(window_id, move |active, cx| {
if let Some(observer) = observer.upgrade(cx) { if let Some(observer) = observer.upgrade(cx) {
observer.update(cx, |observer, cx| { observer.update(cx, |observer, cx| {
callback(observer, active, cx); callback(observer, active, cx);
@ -3680,8 +3546,9 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
) -> bool, ) -> bool,
{ {
let observer = self.weak_handle(); let observer = self.weak_handle();
let window_id = self.window_id;
self.window_context.observe_keystrokes( self.window_context.observe_keystrokes(
self.window_id(), window_id,
move |keystroke, result, handled_by, cx| { move |keystroke, result, handled_by, cx| {
if let Some(observer) = observer.upgrade(cx) { if let Some(observer) = observer.upgrade(cx) {
observer.update(cx, |observer, cx| { observer.update(cx, |observer, cx| {
@ -3700,8 +3567,9 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
F: 'static + FnMut(&mut V, WindowBounds, Uuid, &mut ViewContext<V>), F: 'static + FnMut(&mut V, WindowBounds, Uuid, &mut ViewContext<V>),
{ {
let observer = self.weak_handle(); let observer = self.weak_handle();
let window_id = self.window_id;
self.window_context self.window_context
.observe_window_bounds(self.window_id(), move |bounds, display, cx| { .observe_window_bounds(window_id, move |bounds, display, cx| {
if let Some(observer) = observer.upgrade(cx) { if let Some(observer) = observer.upgrade(cx) {
observer.update(cx, |observer, cx| { observer.update(cx, |observer, cx| {
callback(observer, bounds, display, cx); callback(observer, bounds, display, cx);
@ -3740,18 +3608,23 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
} }
pub fn notify(&mut self) { pub fn notify(&mut self) {
self.window_context let window_id = self.window_id;
.notify_view(self.window_id, self.view_id); let view_id = self.view_id;
self.window_context.notify_view(window_id, view_id);
} }
pub fn dispatch_action(&mut self, action: impl Action) { pub fn dispatch_action(&mut self, action: impl Action) {
let window_id = self.window_id;
let view_id = self.view_id;
self.window_context self.window_context
.dispatch_action_at(self.window_id, self.view_id, action) .dispatch_action_at(window_id, view_id, action)
} }
pub fn dispatch_any_action(&mut self, action: Box<dyn Action>) { pub fn dispatch_any_action(&mut self, action: Box<dyn Action>) {
let window_id = self.window_id;
let view_id = self.view_id;
self.window_context self.window_context
.dispatch_any_action_at(self.window_id, self.view_id, action) .dispatch_any_action_at(window_id, view_id, action)
} }
pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut V, &mut ViewContext<V>)) { pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut V, &mut ViewContext<V>)) {
@ -3813,14 +3686,12 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState { pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState {
let region_id = MouseRegionId::new::<Tag>(self.view_id, region_id); let region_id = MouseRegionId::new::<Tag>(self.view_id, region_id);
MouseState { MouseState {
hovered: self.hovered_region_ids.contains(&region_id), hovered: self.window.hovered_region_ids.contains(&region_id),
clicked: self.clicked_region_ids.as_ref().and_then(|(ids, button)| { clicked: self
if ids.contains(&region_id) { .window
Some(*button) .clicked_region_ids
} else { .get(&region_id)
None .and_then(|_| self.window.clicked_button),
}
}),
accessed_hovered: false, accessed_hovered: false,
accessed_clicked: false, accessed_clicked: false,
} }
@ -3850,7 +3721,7 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
} }
} }
impl<V> UpgradeModelHandle for ViewContext<'_, '_, V> { impl<V> UpgradeModelHandle for ViewContext<'_, '_, '_, V> {
fn upgrade_model_handle<T: Entity>( fn upgrade_model_handle<T: Entity>(
&self, &self,
handle: &WeakModelHandle<T>, handle: &WeakModelHandle<T>,
@ -3867,7 +3738,7 @@ impl<V> UpgradeModelHandle for ViewContext<'_, '_, V> {
} }
} }
impl<V> UpgradeViewHandle for ViewContext<'_, '_, V> { impl<V> UpgradeViewHandle for ViewContext<'_, '_, '_, V> {
fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> { fn upgrade_view_handle<T: View>(&self, handle: &WeakViewHandle<T>) -> Option<ViewHandle<T>> {
self.window_context.upgrade_view_handle(handle) self.window_context.upgrade_view_handle(handle)
} }
@ -3877,7 +3748,13 @@ impl<V> UpgradeViewHandle for ViewContext<'_, '_, V> {
} }
} }
impl<V: View> UpdateModel for ViewContext<'_, '_, V> { impl<V: View> ReadModel for ViewContext<'_, '_, '_, V> {
fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
self.window_context.read_model(handle)
}
}
impl<V: View> UpdateModel for ViewContext<'_, '_, '_, V> {
fn update_model<T: Entity, O>( fn update_model<T: Entity, O>(
&mut self, &mut self,
handle: &ModelHandle<T>, handle: &ModelHandle<T>,
@ -3887,13 +3764,13 @@ impl<V: View> UpdateModel for ViewContext<'_, '_, V> {
} }
} }
impl<V: View> ReadView for ViewContext<'_, '_, V> { impl<V: View> ReadView for ViewContext<'_, '_, '_, V> {
fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T { fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
self.window_context.read_view(handle) self.window_context.read_view(handle)
} }
} }
impl<V: View> UpdateView for ViewContext<'_, '_, V> { impl<V: View> UpdateView for ViewContext<'_, '_, '_, V> {
fn update_view<T, S>( fn update_view<T, S>(
&mut self, &mut self,
handle: &ViewHandle<T>, handle: &ViewHandle<T>,
@ -3906,6 +3783,33 @@ impl<V: View> UpdateView for ViewContext<'_, '_, V> {
} }
} }
enum WindowContextRef<'a, 'b, 'c> {
Immutable(&'c WindowContext<'a, 'b>),
Mutable(&'c mut WindowContext<'a, 'b>),
}
impl<'a, 'b, 'c> Deref for WindowContextRef<'a, 'b, 'c> {
type Target = WindowContext<'a, 'b>;
fn deref(&self) -> &Self::Target {
match self {
WindowContextRef::Immutable(window_context) => window_context,
WindowContextRef::Mutable(window_context) => window_context,
}
}
}
impl<'a, 'b, 'c> DerefMut for WindowContextRef<'a, 'b, 'c> {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
WindowContextRef::Immutable(_) => {
panic!("cannot mutably deref an immutable WindowContext. this is a bug in GPUI.");
}
WindowContextRef::Mutable(window_context) => window_context,
}
}
}
pub struct RenderParams { pub struct RenderParams {
pub window_id: usize, pub window_id: usize,
pub view_id: usize, pub view_id: usize,
@ -4686,9 +4590,10 @@ impl<T: 'static> ElementStateHandle<T> {
.unwrap() .unwrap()
} }
pub fn update<C, R>(&self, cx: &mut C, f: impl FnOnce(&mut T, &mut C) -> R) -> R pub fn update<C, D, R>(&self, cx: &mut C, f: impl FnOnce(&mut T, &mut C) -> R) -> R
where where
C: DerefMut<Target = AppContext>, C: DerefMut<Target = D>,
D: DerefMut<Target = AppContext>,
{ {
let mut element_state = cx.deref_mut().element_states.remove(&self.id).unwrap(); let mut element_state = cx.deref_mut().element_states.remove(&self.id).unwrap();
let result = f(element_state.downcast_mut().unwrap(), cx); let result = f(element_state.downcast_mut().unwrap(), cx);
@ -5104,8 +5009,8 @@ mod tests {
fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox<Self> { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox<Self> {
enum Handler {} enum Handler {}
let mouse_down_count = self.mouse_down_count.clone(); let mouse_down_count = self.mouse_down_count.clone();
MouseEventHandler::<Handler>::new(0, cx, |_, _| Empty::new().boxed()) MouseEventHandler::<Handler, _>::new(0, cx, |_, _| Empty::new().boxed())
.on_down(MouseButton::Left, move |_, _| { .on_down(MouseButton::Left, move |_, _, _| {
mouse_down_count.fetch_add(1, SeqCst); mouse_down_count.fetch_add(1, SeqCst);
}) })
.boxed() .boxed()
@ -5504,8 +5409,8 @@ mod tests {
}); });
view.update(cx, |_, c| { view.update(cx, |_, c| {
c.observe(&model, |me, observed, c| { c.observe(&model, |me, observed, cx| {
me.events.push(observed.read(c).state.clone()) me.events.push(observed.read(cx).state.clone())
}) })
.detach(); .detach();
}); });

View File

@ -78,7 +78,11 @@ pub(crate) fn setup_menu_handlers(foreground_platform: &dyn ForegroundPlatform,
move |action| { move |action| {
let mut cx = cx.borrow_mut(); let mut cx = cx.borrow_mut();
if let Some(main_window_id) = cx.platform.main_window_id() { if let Some(main_window_id) = cx.platform.main_window_id() {
if let Some(view_id) = cx.focused_view_id(main_window_id) { if let Some(view_id) = cx
.windows
.get(&main_window_id)
.and_then(|w| w.focused_view_id)
{
cx.handle_dispatch_action_from_effect(main_window_id, Some(view_id), action); cx.handle_dispatch_action_from_effect(main_window_id, Some(view_id), action);
return; return;
} }

View File

@ -1,6 +1,5 @@
use std::{ use std::{
cell::RefCell, cell::RefCell,
marker::PhantomData,
mem, mem,
path::PathBuf, path::PathBuf,
rc::Rc, rc::Rc,
@ -21,7 +20,7 @@ use crate::{
geometry::vector::Vector2F, geometry::vector::Vector2F,
keymap_matcher::Keystroke, keymap_matcher::Keystroke,
platform, platform,
platform::{Appearance, Event, InputHandler, KeyDownEvent, Platform}, platform::{Event, InputHandler, KeyDownEvent, Platform},
Action, AnyViewHandle, AppContext, Entity, FontCache, Handle, ModelContext, ModelHandle, Action, AnyViewHandle, AppContext, Entity, FontCache, Handle, ModelContext, ModelHandle,
ReadModelWith, ReadViewWith, Task, UpdateModel, UpdateView, View, ViewContext, ViewHandle, ReadModelWith, ReadViewWith, Task, UpdateModel, UpdateView, View, ViewContext, ViewHandle,
WeakHandle, WeakHandle,
@ -74,7 +73,7 @@ impl TestAppContext {
pub fn dispatch_action<A: Action>(&self, window_id: usize, action: A) { pub fn dispatch_action<A: Action>(&self, window_id: usize, action: A) {
let mut cx = self.cx.borrow_mut(); let mut cx = self.cx.borrow_mut();
if let Some(view_id) = cx.focused_view_id { if let Some(view_id) = cx.windows.get(&window_id).and_then(|w| w.focused_view_id) {
cx.handle_dispatch_action_from_effect(window_id, Some(view_id), &action); cx.handle_dispatch_action_from_effect(window_id, Some(view_id), &action);
} }
} }
@ -149,7 +148,14 @@ impl TestAppContext {
} }
pub fn root_view(&self, window_id: usize) -> Option<AnyViewHandle> { pub fn root_view(&self, window_id: usize) -> Option<AnyViewHandle> {
self.cx.borrow().root_view(window_id) Some(
self.cx
.borrow()
.windows
.get(&window_id)?
.root_view()
.clone(),
)
} }
pub fn read<T, F: FnOnce(&AppContext) -> T>(&self, callback: F) -> T { pub fn read<T, F: FnOnce(&AppContext) -> T>(&self, callback: F) -> T {
@ -172,20 +178,21 @@ impl TestAppContext {
F: FnOnce(&mut V, &mut ViewContext<V>) -> T, F: FnOnce(&mut V, &mut ViewContext<V>) -> T,
V: View, V: View,
{ {
handle.update(&mut *self.cx.borrow_mut(), |view, cx| { todo!()
let mut render_cx = ViewContext { // handle.update(&mut *self.cx.borrow_mut(), |view, cx| {
app: cx, // let mut render_cx = ViewContext {
window_id: handle.window_id(), // app: cx,
view_id: handle.id(), // window_id: handle.window_id(),
view_type: PhantomData, // view_id: handle.id(),
titlebar_height: 0., // view_type: PhantomData,
hovered_region_ids: Default::default(), // titlebar_height: 0.,
clicked_region_ids: None, // hovered_region_ids: Default::default(),
refreshing: false, // clicked_region_ids: None,
appearance: Appearance::Light, // refreshing: false,
}; // appearance: Appearance::Light,
f(view, &mut render_cx) // };
}) // f(view, &mut render_cx)
// })
} }
pub fn to_async(&self) -> AsyncAppContext { pub fn to_async(&self) -> AsyncAppContext {

View File

@ -1,6 +1,4 @@
use crate::{ use crate::{
app::WindowInvalidation,
elements::Element,
geometry::rect::RectF, geometry::rect::RectF,
json::{self, ToJson}, json::{self, ToJson},
keymap_matcher::{Keystroke, MatchResult}, keymap_matcher::{Keystroke, MatchResult},
@ -13,8 +11,9 @@ use crate::{
MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene,
}, },
text_layout::TextLayoutCache, text_layout::TextLayoutCache,
Action, AnyView, AnyViewHandle, AnyWeakViewHandle, AppContext, ElementBox, MouseRegion, util::post_inc,
MouseRegionId, RenderParams, SceneBuilder, View, AnyView, AnyViewHandle, AppContext, Element, ElementBox, MouseRegion, MouseRegionId, ParentId,
RenderParams, SceneBuilder, View, ViewContext, ViewHandle, WindowInvalidation,
}; };
use anyhow::bail; use anyhow::bail;
use collections::{HashMap, HashSet}; use collections::{HashMap, HashSet};
@ -30,8 +29,7 @@ use std::ops::{Deref, DerefMut, Range};
use uuid::Uuid; use uuid::Uuid;
pub struct Window { pub struct Window {
window_id: usize, pub(crate) root_view: Option<AnyViewHandle>,
pub(crate) root_view: AnyViewHandle,
pub(crate) focused_view_id: Option<usize>, pub(crate) focused_view_id: Option<usize>,
pub(crate) is_active: bool, pub(crate) is_active: bool,
pub(crate) is_fullscreen: bool, pub(crate) is_fullscreen: bool,
@ -43,27 +41,29 @@ pub struct Window {
cursor_regions: Vec<CursorRegion>, cursor_regions: Vec<CursorRegion>,
mouse_regions: Vec<(MouseRegion, usize)>, mouse_regions: Vec<(MouseRegion, usize)>,
last_mouse_moved_event: Option<Event>, last_mouse_moved_event: Option<Event>,
hovered_region_ids: HashSet<MouseRegionId>, pub(crate) hovered_region_ids: HashSet<MouseRegionId>,
clicked_region_ids: HashSet<MouseRegionId>, pub(crate) clicked_region_ids: HashSet<MouseRegionId>,
clicked_button: Option<MouseButton>, pub(crate) clicked_button: Option<MouseButton>,
mouse_position: Vector2F, mouse_position: Vector2F,
text_layout_cache: TextLayoutCache, text_layout_cache: TextLayoutCache,
} }
impl Window { impl Window {
pub fn new( pub fn new<V, F>(
window_id: usize, window_id: usize,
root_view: AnyViewHandle,
platform_window: Box<dyn platform::Window>, platform_window: Box<dyn platform::Window>,
cx: &mut AppContext, cx: &mut AppContext,
) -> Self { build_view: F,
let focused_view_id = Some(root_view.id()); ) -> Self
where
F: FnOnce(&mut ViewContext<V>) -> V,
V: View,
{
let titlebar_height = platform_window.titlebar_height(); let titlebar_height = platform_window.titlebar_height();
let appearance = platform_window.appearance(); let appearance = platform_window.appearance();
Self { let mut window = Self {
window_id, root_view: None,
root_view, focused_view_id: None,
focused_view_id,
is_active: false, is_active: false,
invalidation: None, invalidation: None,
is_fullscreen: false, is_fullscreen: false,
@ -79,15 +79,30 @@ impl Window {
mouse_position: vec2f(0., 0.), mouse_position: vec2f(0., 0.),
titlebar_height, titlebar_height,
appearance, appearance,
};
let mut window_context = WindowContext::new(cx, &mut window, window_id);
let root_view = window_context
.build_and_insert_view(ParentId::Root, |cx| Some(build_view(cx)))
.unwrap();
window.focused_view_id = Some(root_view.id());
window.root_view = Some(root_view.into_any());
window
} }
pub fn root_view(&self) -> &AnyViewHandle {
&self
.root_view
.as_ref()
.expect("root_view called during window construction")
} }
} }
pub struct WindowContext<'a: 'b, 'b> { pub struct WindowContext<'a: 'b, 'b> {
app_context: &'a mut AppContext, pub(crate) app_context: &'a mut AppContext,
pub(crate) window: &'b mut Window, // TODO: make this private? pub(crate) window: &'b mut Window, // TODO: make this private?
pub(crate) window_id: usize, pub(crate) window_id: usize,
pub refreshing: bool, pub(crate) refreshing: bool,
} }
impl Deref for WindowContext<'_, '_> { impl Deref for WindowContext<'_, '_> {
@ -110,16 +125,30 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
app_context, app_context,
window, window,
window_id, window_id,
refreshing: false,
} }
} }
pub fn update_any_view<F, T>(&mut self, view_id: usize, f: F) -> Option<T> pub fn window_id(&self) -> usize {
self.window_id
}
pub fn window_size(&self) -> Vector2F {
self.window.platform_window.content_size()
}
pub fn text_layout_cache(&self) -> &TextLayoutCache {
&self.window.text_layout_cache
}
pub(crate) fn update_any_view<F, T>(&mut self, view_id: usize, f: F) -> Option<T>
where where
F: FnOnce(&mut dyn AnyView, &mut Self) -> T, F: FnOnce(&mut dyn AnyView, &mut Self) -> T,
{ {
let view = self.views.remove(&(self.window_id, view_id))?; let window_id = self.window_id;
let result = f(view.as_any_mut(), self); let mut view = self.views.remove(&(window_id, view_id))?;
self.views.insert((self.window_id, view_id), view); let result = f(view.as_mut(), self);
self.views.insert((window_id, view_id), view);
Some(result) Some(result)
} }
@ -453,8 +482,7 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
//3. Fire region events //3. Fire region events
let hovered_region_ids = self.window.hovered_region_ids.clone(); let hovered_region_ids = self.window.hovered_region_ids.clone();
for valid_region in valid_regions.into_iter() { for valid_region in valid_regions.into_iter() {
let mut event_cx = self.build_event_context(&mut notified_views); let mut handled = false;
mouse_event.set_region(valid_region.bounds); mouse_event.set_region(valid_region.bounds);
if let MouseEvent::Hover(e) = &mut mouse_event { if let MouseEvent::Hover(e) = &mut mouse_event {
e.started = hovered_region_ids.contains(&valid_region.id()) e.started = hovered_region_ids.contains(&valid_region.id())
@ -473,25 +501,25 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
.handlers .handlers
.contains(MouseEvent::down_disc(), Some(e.button)); .contains(MouseEvent::down_disc(), Some(e.button));
if !has_down && (has_click || has_drag) { if !has_down && (has_click || has_drag) {
event_cx.handled = true; handled = true;
} }
} }
// `event_consumed` should only be true if there are any handlers for this event. // `event_consumed` should only be true if there are any handlers for this event.
let mut event_consumed = event_cx.handled; let mut event_consumed = handled;
if let Some(callbacks) = valid_region.handlers.get(&mouse_event.handler_key()) { if let Some(callbacks) = valid_region.handlers.get(&mouse_event.handler_key()) {
for callback in callbacks { for callback in callbacks {
event_cx.handled = true; handled = true;
event_cx.with_current_view(valid_region.id().view_id(), { let view_id = valid_region.id().view_id();
let region_event = mouse_event.clone(); self.update_any_view(view_id, |view, cx| {
|cx| callback(region_event, cx) handled = callback(mouse_event.clone(), view.as_any_mut(), cx, view_id);
}); });
event_consumed |= event_cx.handled; event_consumed |= handled;
any_event_handled |= event_cx.handled; any_event_handled |= handled;
} }
} }
any_event_handled |= event_cx.handled; any_event_handled |= handled;
// For bubbling events, if the event was handled, don't continue dispatching. // For bubbling events, if the event was handled, don't continue dispatching.
// This only makes sense for local events which return false from is_capturable. // This only makes sense for local events which return false from is_capturable.
@ -530,7 +558,7 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
} }
pub fn dispatch_key_up(&mut self, window_id: usize, event: &KeyUpEvent) -> bool { pub fn dispatch_key_up(&mut self, window_id: usize, event: &KeyUpEvent) -> bool {
if let Some(focused_view_id) = self.window.fo { if let Some(focused_view_id) = self.window.focused_view_id {
for view_id in self for view_id in self
.ancestors(window_id, focused_view_id) .ancestors(window_id, focused_view_id)
.collect::<Vec<_>>() .collect::<Vec<_>>()
@ -645,18 +673,17 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
let window_size = self.window.platform_window.content_size(); let window_size = self.window.platform_window.content_size();
let scale_factor = self.window.platform_window.scale_factor(); let scale_factor = self.window.platform_window.scale_factor();
let root_view_id = self.window.root_view.id(); let root_view_id = self.window.root_view().id();
let rendered_root = self.window.rendered_views.remove(&root_view_id).unwrap(); let mut rendered_root = self.window.rendered_views.remove(&root_view_id).unwrap();
rendered_root.layout(root_view_id, SizeConstraint::strict(window_size), self); rendered_root.layout(SizeConstraint::strict(window_size), self, root_view_id);
let mut scene_builder = SceneBuilder::new(scale_factor); let mut scene_builder = SceneBuilder::new(scale_factor);
let paint_bounds = RectF::from_points(Vector2F::zero(), window_size);
rendered_root.paint( rendered_root.paint(
root_view_id,
&mut scene_builder, &mut scene_builder,
paint_bounds, Vector2F::zero(),
paint_bounds, RectF::from_points(Vector2F::zero(), window_size),
self, self,
root_view_id,
); );
self.window.text_layout_cache.finish_frame(); self.window.text_layout_cache.finish_frame();
@ -719,14 +746,6 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
self.window.is_fullscreen self.window.is_fullscreen
} }
pub fn root_view(&self, window_id: usize) -> &AnyViewHandle {
&self.window.root_view
}
pub fn root_view_id(&self) -> usize {
self.window.root_view.id()
}
pub fn focused_view_id(&self) -> Option<usize> { pub fn focused_view_id(&self) -> Option<usize> {
self.window.focused_view_id self.window.focused_view_id
} }
@ -739,7 +758,7 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
self.window.platform_window.screen().display_uuid() self.window.platform_window.screen().display_uuid()
} }
fn show_character_palette(&self) { pub fn show_character_palette(&self) {
self.window.platform_window.show_character_palette(); self.window.platform_window.show_character_palette();
} }
@ -763,47 +782,162 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
) -> oneshot::Receiver<usize> { ) -> oneshot::Receiver<usize> {
self.window.platform_window.prompt(level, msg, answers) self.window.platform_window.prompt(level, msg, answers)
} }
fn add_view<T, F>(&mut self, parent: &AnyViewHandle, build_view: F) -> ViewHandle<T>
where
T: View,
F: FnOnce(&mut ViewContext<T>) -> T,
{
if parent.window_id == self.window_id {
self.build_and_insert_view(ParentId::View(parent.view_id), |cx| Some(build_view(cx)))
.unwrap()
} else {
self.app_context.add_view(parent, build_view)
}
}
fn add_option_view<T, F>(
&mut self,
parent_handle: impl Into<AnyViewHandle>,
build_view: F,
) -> Option<ViewHandle<T>>
where
T: View,
F: FnOnce(&mut ViewContext<T>) -> Option<T>,
{
let parent_handle = parent_handle.into();
self.build_and_insert_view(ParentId::View(parent_handle.view_id), build_view)
}
pub fn replace_root_view<V, F>(&mut self, build_root_view: F) -> ViewHandle<V>
where
V: View,
F: FnOnce(&mut ViewContext<V>) -> V,
{
let root_view = self
.build_and_insert_view(ParentId::Root, |cx| Some(build_root_view(cx)))
.unwrap();
self.window.root_view = Some(root_view.clone().into_any());
self.window.focused_view_id = Some(root_view.id());
root_view
}
pub(crate) fn build_and_insert_view<T, F>(
&mut self,
parent_id: ParentId,
build_view: F,
) -> Option<ViewHandle<T>>
where
T: View,
F: FnOnce(&mut ViewContext<T>) -> Option<T>,
{
let window_id = self.window_id;
let view_id = post_inc(&mut self.next_entity_id);
// Make sure we can tell child views about their parentu
self.parents.insert((window_id, view_id), parent_id);
let mut cx = ViewContext::mutable(self, view_id);
let handle = if let Some(view) = build_view(&mut cx) {
self.views.insert((window_id, view_id), Box::new(view));
self.window
.invalidation
.get_or_insert_with(Default::default)
.updated
.insert(view_id);
Some(ViewHandle::new(window_id, view_id, &self.ref_counts))
} else {
self.parents.remove(&(window_id, view_id));
None
};
handle
}
} }
pub trait RenderedView { pub trait RenderedView {
fn layout( fn layout(
&self, &mut self,
view_id: usize,
constraint: SizeConstraint, constraint: SizeConstraint,
cx: &mut WindowContext, cx: &mut WindowContext,
view_id: usize,
) -> Vector2F; ) -> Vector2F;
fn paint( fn paint(
&self, &mut self,
view_id: usize,
scene: &mut SceneBuilder, scene: &mut SceneBuilder,
bounds: RectF, origin: Vector2F,
visible_bounds: RectF, visible_bounds: RectF,
cx: &mut WindowContext, cx: &mut WindowContext,
view_id: usize,
); );
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
cx: &WindowContext,
view_id: usize,
) -> Option<RectF>;
fn debug(&self, cx: &WindowContext, view_id: usize) -> serde_json::Value;
fn name(&self) -> Option<&str>;
} }
impl<V: View> RenderedView for ElementBox<V> { impl<V: View> RenderedView for ElementBox<V> {
fn layout( fn layout(
&self, &mut self,
view_id: usize,
constraint: SizeConstraint, constraint: SizeConstraint,
cx: &mut WindowContext, cx: &mut WindowContext,
view_id: usize,
) -> Vector2F { ) -> Vector2F {
cx.update_view_for_id(view_id, |view, cx| self.layout(view, constraint, cx)) cx.update_any_view(view_id, |view, cx| {
let view = view.as_any_mut().downcast_mut::<V>().unwrap();
let mut cx = ViewContext::mutable(cx, view_id);
ElementBox::layout(self, constraint, view, &mut cx)
})
.unwrap() .unwrap()
} }
fn paint( fn paint(
&self, &mut self,
view_id: usize,
scene: &mut SceneBuilder, scene: &mut SceneBuilder,
bounds: RectF, origin: Vector2F,
visible_bounds: RectF, visible_bounds: RectF,
cx: &mut WindowContext, cx: &mut WindowContext,
view_id: usize,
) { ) {
cx.update_view_for_id(view_id, |view, cx| { cx.update_any_view(view_id, |view, cx| {
self.paint(view, scene, bounds, visible_bounds, cx) let view = view.as_any_mut().downcast_mut::<V>().unwrap();
}) let mut cx = ViewContext::mutable(cx, view_id);
ElementBox::paint(self, scene, origin, visible_bounds, view, &mut cx)
});
}
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
cx: &WindowContext,
view_id: usize,
) -> Option<RectF> {
let view = cx
.views
.get(&(cx.window_id, view_id))
.unwrap()
.as_any()
.downcast_ref::<V>()
.unwrap();
let cx = ViewContext::immutable(cx, view_id);
ElementBox::rect_for_text_range(self, range_utf16, view, &cx)
}
fn debug(&self, cx: &WindowContext, view_id: usize) -> serde_json::Value {
let view = cx
.views
.get(&(cx.window_id, view_id))
.unwrap()
.as_any()
.downcast_ref::<V>()
.unwrap();
let cx = ViewContext::immutable(cx, view_id);
ElementBox::debug(self, view, &cx)
}
fn name(&self) -> Option<&str> {
ElementBox::name(self)
} }
} }
@ -950,7 +1084,7 @@ impl ToJson for SizeConstraint {
} }
pub struct ChildView { pub struct ChildView {
view: AnyWeakViewHandle, view_id: usize,
view_name: &'static str, view_name: &'static str,
} }
@ -958,94 +1092,101 @@ impl ChildView {
pub fn new(view: &AnyViewHandle, cx: &AppContext) -> Self { pub fn new(view: &AnyViewHandle, cx: &AppContext) -> Self {
let view_name = cx.view_ui_name(view.window_id(), view.id()).unwrap(); let view_name = cx.view_ui_name(view.window_id(), view.id()).unwrap();
Self { Self {
view: view.downgrade(), view_id: view.id(),
view_name, view_name,
} }
} }
} }
// impl Element for ChildView { impl<V: View> Element<V> for ChildView {
// type LayoutState = bool; type LayoutState = ();
// type PaintState = (); type PaintState = ();
// fn layout( fn layout(
// &mut self, &mut self,
// constraint: SizeConstraint, constraint: SizeConstraint,
// cx: &mut LayoutContext, _: &mut V,
// ) -> (Vector2F, Self::LayoutState) { cx: &mut ViewContext<V>,
// if cx.rendered_views.contains_key(&self.view.id()) { ) -> (Vector2F, Self::LayoutState) {
// let size = cx.layout(self.view.id(), constraint); if let Some(mut rendered_view) = cx.window.rendered_views.remove(&self.view_id) {
// (size, true) let size = rendered_view.layout(constraint, cx, self.view_id);
// } else { cx.window.rendered_views.insert(self.view_id, rendered_view);
// log::error!( (size, ())
// "layout called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})", } else {
// self.view.id(), log::error!(
// self.view_name "layout called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
// ); self.view_id,
// (Vector2F::zero(), false) self.view_name
// } );
// } (Vector2F::zero(), ())
}
}
// fn paint( fn paint(
// &mut self, &mut self,
// bounds: RectF, scene: &mut SceneBuilder,
// visible_bounds: RectF, bounds: RectF,
// view_is_valid: &mut Self::LayoutState, visible_bounds: RectF,
// cx: &mut PaintContext, _: &mut Self::LayoutState,
// ) { _: &mut V,
// if *view_is_valid { cx: &mut ViewContext<V>,
// cx.paint(self.view.id(), bounds.origin(), visible_bounds); ) {
// } else { if let Some(mut rendered_view) = cx.window.rendered_views.remove(&self.view_id) {
// log::error!( rendered_view.paint(scene, bounds.origin(), visible_bounds, cx, self.view_id);
// "paint called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})", cx.window.rendered_views.insert(self.view_id, rendered_view);
// self.view.id(), } else {
// self.view_name log::error!(
// ); "paint called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
// } self.view_id,
// } self.view_name
);
}
}
// fn rect_for_text_range( fn rect_for_text_range(
// &self, &self,
// range_utf16: Range<usize>, range_utf16: Range<usize>,
// _: RectF, _: RectF,
// _: RectF, _: RectF,
// view_is_valid: &Self::LayoutState, _: &Self::LayoutState,
// _: &Self::PaintState, _: &Self::PaintState,
// cx: &MeasurementContext, _: &V,
// ) -> Option<RectF> { cx: &ViewContext<V>,
// if *view_is_valid { ) -> Option<RectF> {
// cx.rect_for_text_range(self.view.id(), range_utf16) if let Some(rendered_view) = cx.window.rendered_views.get(&self.view_id) {
// } else { rendered_view.rect_for_text_range(range_utf16, &cx.window_context, self.view_id)
// log::error!( } else {
// "rect_for_text_range called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})", log::error!(
// self.view.id(), "rect_for_text_range called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
// self.view_name self.view_id,
// ); self.view_name
// None );
// } None
// } }
}
// fn debug( fn debug(
// &self, &self,
// bounds: RectF, bounds: RectF,
// _: &Self::LayoutState, _: &Self::LayoutState,
// _: &Self::PaintState, _: &Self::PaintState,
// cx: &DebugContext, _: &V,
// ) -> serde_json::Value { cx: &ViewContext<V>,
// json!({ ) -> serde_json::Value {
// "type": "ChildView", json!({
// "view_id": self.view.id(), "type": "ChildView",
// "bounds": bounds.to_json(), "view_id": self.view_id,
// "view": if let Some(view) = self.view.upgrade(cx.app) { "bounds": bounds.to_json(),
// view.debug_json(cx.app) "view": if let Some(view) = cx.views.get(&(cx.window_id, self.view_id)) {
// } else { view.debug_json(cx)
// json!(null) } else {
// }, json!(null)
// "child": if let Some(view) = cx.rendered_views.get(&self.view.id()) { },
// view.debug(cx) "child": if let Some(element) = cx.window.rendered_views.get(&self.view_id) {
// } else { element.debug(&cx.window_context, self.view_id)
// json!(null) } else {
// } json!(null)
// }) }
// } })
// } }
}

View File

@ -2,7 +2,7 @@ use std::{cell::RefCell, ops::Range, rc::Rc};
use pathfinder_geometry::rect::RectF; use pathfinder_geometry::rect::RectF;
use crate::{platform::InputHandler, AnyView, AppContext}; use crate::{platform::InputHandler, window::WindowContext, AnyView, AppContext};
pub struct WindowInputHandler { pub struct WindowInputHandler {
pub app: Rc<RefCell<AppContext>>, pub app: Rc<RefCell<AppContext>>,
@ -12,7 +12,7 @@ pub struct WindowInputHandler {
impl WindowInputHandler { impl WindowInputHandler {
fn read_focused_view<T, F>(&self, f: F) -> Option<T> fn read_focused_view<T, F>(&self, f: F) -> Option<T>
where where
F: FnOnce(&dyn AnyView, &AppContext) -> T, F: FnOnce(&dyn AnyView, &WindowContext) -> T,
{ {
// Input-related application hooks are sometimes called by the OS during // Input-related application hooks are sometimes called by the OS during
// a call to a window-manipulation API, like prompting the user for file // a call to a window-manipulation API, like prompting the user for file
@ -20,26 +20,26 @@ impl WindowInputHandler {
// InputHandler methods need to fail gracefully. // InputHandler methods need to fail gracefully.
// //
// See https://github.com/zed-industries/community/issues/444 // See https://github.com/zed-industries/community/issues/444
let app = self.app.try_borrow().ok()?; let mut app = self.app.try_borrow_mut().ok()?;
app.update_window(self.window_id, |cx| {
let view_id = app.focused_view_id(self.window_id)?; let view_id = cx.window.focused_view_id?;
let view = app.views.get(&(self.window_id, view_id))?; let view = cx.views.get(&(self.window_id, view_id))?;
let result = f(view.as_ref(), &app); let result = f(view.as_ref(), &cx);
Some(result) Some(result)
})
.flatten()
} }
fn update_focused_view<T, F>(&mut self, f: F) -> Option<T> fn update_focused_view<T, F>(&mut self, f: F) -> Option<T>
where where
F: FnOnce(usize, usize, &mut dyn AnyView, &mut AppContext) -> T, F: FnOnce(&mut dyn AnyView, &mut WindowContext, usize) -> T,
{ {
let mut app = self.app.try_borrow_mut().ok()?; let mut app = self.app.try_borrow_mut().ok()?;
app.update(|app| { app.update_window(self.window_id, |cx| {
let view_id = app.focused_view_id(self.window_id)?; let view_id = cx.window.focused_view_id?;
let mut view = app.views.remove(&(self.window_id, view_id))?; cx.update_any_view(view_id, |view, cx| f(view, cx, view_id))
let result = f(self.window_id, view_id, view.as_mut(), &mut *app);
app.views.insert((self.window_id, view_id), view);
Some(result)
}) })
.flatten()
} }
} }
@ -55,8 +55,8 @@ impl InputHandler for WindowInputHandler {
} }
fn replace_text_in_range(&mut self, range: Option<Range<usize>>, text: &str) { fn replace_text_in_range(&mut self, range: Option<Range<usize>>, text: &str) {
self.update_focused_view(|window_id, view_id, view, cx| { self.update_focused_view(|view, cx, view_id| {
view.replace_text_in_range(range, text, cx, window_id, view_id); view.replace_text_in_range(range, text, cx, view_id);
}); });
} }
@ -66,8 +66,8 @@ impl InputHandler for WindowInputHandler {
} }
fn unmark_text(&mut self) { fn unmark_text(&mut self) {
self.update_focused_view(|window_id, view_id, view, cx| { self.update_focused_view(|view, cx, view_id| {
view.unmark_text(cx, window_id, view_id); view.unmark_text(cx, view_id);
}); });
} }
@ -77,15 +77,8 @@ impl InputHandler for WindowInputHandler {
new_text: &str, new_text: &str,
new_selected_range: Option<Range<usize>>, new_selected_range: Option<Range<usize>>,
) { ) {
self.update_focused_view(|window_id, view_id, view, cx| { self.update_focused_view(|view, cx, view_id| {
view.replace_and_mark_text_in_range( view.replace_and_mark_text_in_range(range, new_text, new_selected_range, cx, view_id);
range,
new_text,
new_selected_range,
cx,
window_id,
view_id,
);
}); });
} }

View File

@ -35,29 +35,29 @@ use crate::{
}; };
use core::panic; use core::panic;
use json::ToJson; use json::ToJson;
use std::{any::Any, borrow::Cow, cell::RefCell, marker::PhantomData, mem, ops::Range}; use std::{any::Any, borrow::Cow, marker::PhantomData, mem, ops::Range};
trait AnyElement<V: View> { trait AnyElement<V: View> {
fn layout( fn layout(
&mut self, &mut self,
view: &mut V,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Vector2F; ) -> Vector2F;
fn paint( fn paint(
&mut self, &mut self,
view: &mut V,
scene: &mut SceneBuilder, scene: &mut SceneBuilder,
origin: Vector2F, origin: Vector2F,
visible_bounds: RectF, visible_bounds: RectF,
view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
); );
fn rect_for_text_range( fn rect_for_text_range(
&self, &self,
view: &V,
range_utf16: Range<usize>, range_utf16: Range<usize>,
view: &V,
cx: &ViewContext<V>, cx: &ViewContext<V>,
) -> Option<RectF>; ) -> Option<RectF>;
@ -118,7 +118,8 @@ pub trait Element<V: View> {
Self: 'static + Sized, Self: 'static + Sized,
{ {
ElementBox { ElementBox {
element: RefCell::new(Lifecycle::Init { element: self }), element: Box::new(Lifecycle::Init { element: self }),
view_type: PhantomData,
name: None, name: None,
} }
} }
@ -128,7 +129,8 @@ pub trait Element<V: View> {
Self: 'static + Sized, Self: 'static + Sized,
{ {
ElementBox { ElementBox {
element: RefCell::new(Lifecycle::Init { element: self }), element: Box::new(Lifecycle::Init { element: self }),
view_type: PhantomData,
name: Some(name.into()), name: Some(name.into()),
} }
} }
@ -193,7 +195,7 @@ pub trait Element<V: View> {
where where
Self: 'static + Sized, Self: 'static + Sized,
{ {
Tooltip::new::<Tag>(id, text, action, style, self.boxed(), cx) Tooltip::new::<Tag, V>(id, text, action, style, self.boxed(), cx)
} }
fn with_resize_handle<Tag: 'static>( fn with_resize_handle<Tag: 'static>(
@ -207,7 +209,7 @@ pub trait Element<V: View> {
where where
Self: 'static + Sized, Self: 'static + Sized,
{ {
Resizable::new::<Tag>( Resizable::new::<Tag, V>(
self.boxed(), self.boxed(),
element_id, element_id,
side, side,
@ -242,8 +244,8 @@ pub enum Lifecycle<V: View, E: Element<V>> {
impl<V: View, E: Element<V>> AnyElement<V> for Lifecycle<V, E> { impl<V: View, E: Element<V>> AnyElement<V> for Lifecycle<V, E> {
fn layout( fn layout(
&mut self, &mut self,
view: &mut V,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Vector2F { ) -> Vector2F {
let result; let result;
@ -252,7 +254,7 @@ impl<V: View, E: Element<V>> AnyElement<V> for Lifecycle<V, E> {
Lifecycle::Init { mut element } Lifecycle::Init { mut element }
| Lifecycle::PostLayout { mut element, .. } | Lifecycle::PostLayout { mut element, .. }
| Lifecycle::PostPaint { mut element, .. } => { | Lifecycle::PostPaint { mut element, .. } => {
let (size, layout) = element.layout(view, constraint, cx); let (size, layout) = element.layout(constraint, view, cx);
debug_assert!(size.x().is_finite()); debug_assert!(size.x().is_finite());
debug_assert!(size.y().is_finite()); debug_assert!(size.y().is_finite());
@ -271,9 +273,9 @@ impl<V: View, E: Element<V>> AnyElement<V> for Lifecycle<V, E> {
fn paint( fn paint(
&mut self, &mut self,
scene: &mut SceneBuilder, scene: &mut SceneBuilder,
view: &mut V,
origin: Vector2F, origin: Vector2F,
visible_bounds: RectF, visible_bounds: RectF,
view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) { ) {
*self = match mem::take(self) { *self = match mem::take(self) {
@ -321,9 +323,9 @@ impl<V: View, E: Element<V>> AnyElement<V> for Lifecycle<V, E> {
fn rect_for_text_range( fn rect_for_text_range(
&self, &self,
view: &V,
range_utf16: Range<usize>, range_utf16: Range<usize>,
cx: &mut ViewContext<V>, view: &V,
cx: &ViewContext<V>,
) -> Option<RectF> { ) -> Option<RectF> {
if let Lifecycle::PostPaint { if let Lifecycle::PostPaint {
element, element,
@ -404,41 +406,40 @@ impl<V: View, E: Element<V>> Default for Lifecycle<V, E> {
} }
pub struct ElementBox<V: View> { pub struct ElementBox<V: View> {
element: Box<RefCell<dyn AnyElement<V>>>, element: Box<dyn AnyElement<V>>,
view_type: PhantomData<V>, view_type: PhantomData<V>,
name: Option<Cow<'static, str>>, name: Option<Cow<'static, str>>,
} }
impl<V: View> ElementBox<V> { impl<V: View> ElementBox<V> {
pub fn name(&self) -> Option<&str> { pub fn name(&self) -> Option<&str> {
self.0.name.as_deref() self.name.as_deref()
} }
pub fn metadata<T: 'static>(&self) -> Option<&T> { pub fn metadata<T: 'static>(&self) -> Option<&T> {
// let element = unsafe { &*self.0.element.as_ptr() }; self.element
// element.metadata().and_then(|m| m.downcast_ref()) .metadata()
.and_then(|data| data.downcast_ref::<T>())
} }
pub fn layout( pub fn layout(
&self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Vector2F { ) -> Vector2F {
self.element.borrow_mut().layout(view, constraint, cx) self.element.layout(constraint, view, cx)
} }
pub fn paint( pub fn paint(
&self, &mut self,
scene: &mut SceneBuilder, scene: &mut SceneBuilder,
origin: Vector2F, origin: Vector2F,
visible_bounds: RectF, visible_bounds: RectF,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) { ) {
self.element self.element.paint(scene, origin, visible_bounds, view, cx);
.borrow_mut()
.paint(view, scene, origin, visible_bounds, cx);
} }
pub fn rect_for_text_range( pub fn rect_for_text_range(
@ -447,17 +448,15 @@ impl<V: View> ElementBox<V> {
view: &V, view: &V,
cx: &ViewContext<V>, cx: &ViewContext<V>,
) -> Option<RectF> { ) -> Option<RectF> {
self.element self.element.rect_for_text_range(range_utf16, view, cx)
.borrow()
.rect_for_text_range(view, range_utf16, cx)
} }
pub fn size(&self) -> Vector2F { pub fn size(&self) -> Vector2F {
self.element.borrow().size() self.element.size()
} }
pub fn debug(&self, view: &V, cx: &ViewContext<V>) -> json::Value { pub fn debug(&self, view: &V, cx: &ViewContext<V>) -> json::Value {
let mut value = self.element.borrow().debug(view, cx); let mut value = self.element.debug(view, cx);
if let Some(name) = &self.name { if let Some(name) = &self.name {
if let json::Value::Object(map) = &mut value { if let json::Value::Object(map) = &mut value {
@ -476,8 +475,7 @@ impl<V: View> ElementBox<V> {
T: 'static, T: 'static,
F: FnOnce(Option<&T>) -> R, F: FnOnce(Option<&T>) -> R,
{ {
let element = self.element.borrow(); f(self.element.metadata().and_then(|m| m.downcast_ref()))
f(element.metadata().and_then(|m| m.downcast_ref()))
} }
} }

View File

@ -46,13 +46,13 @@ impl<V: View> Element<V> for Align<V> {
fn layout( fn layout(
&mut self, &mut self,
view: &mut V,
mut constraint: SizeConstraint, mut constraint: SizeConstraint,
view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let mut size = constraint.max; let mut size = constraint.max;
constraint.min = Vector2F::zero(); constraint.min = Vector2F::zero();
let child_size = self.child.layout(view, constraint, cx); let child_size = self.child.layout(constraint, view, cx);
if size.x().is_infinite() { if size.x().is_infinite() {
size.set_x(child_size.x()); size.set_x(child_size.x());
} }
@ -64,11 +64,11 @@ impl<V: View> Element<V> for Align<V> {
fn paint( fn paint(
&mut self, &mut self,
view: &mut V,
scene: &mut SceneBuilder, scene: &mut SceneBuilder,
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
_: &mut Self::LayoutState, _: &mut Self::LayoutState,
view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
let my_center = bounds.size() / 2.; let my_center = bounds.size() / 2.;
@ -78,33 +78,33 @@ impl<V: View> Element<V> for Align<V> {
let child_target = child_center + child_center * self.alignment; let child_target = child_center + child_center * self.alignment;
self.child.paint( self.child.paint(
view,
scene, scene,
bounds.origin() - (child_target - my_target), bounds.origin() - (child_target - my_target),
visible_bounds, visible_bounds,
view,
cx, cx,
); );
} }
fn rect_for_text_range( fn rect_for_text_range(
&self, &self,
view: &V,
range_utf16: std::ops::Range<usize>, range_utf16: std::ops::Range<usize>,
_: RectF, _: RectF,
_: RectF, _: RectF,
_: &Self::LayoutState, _: &Self::LayoutState,
_: &Self::PaintState, _: &Self::PaintState,
view: &V,
cx: &ViewContext<V>, cx: &ViewContext<V>,
) -> Option<RectF> { ) -> Option<RectF> {
self.child.rect_for_text_range(view, range_utf16, cx) self.child.rect_for_text_range(range_utf16, view, cx)
} }
fn debug( fn debug(
&self, &self,
view: &V,
bounds: pathfinder_geometry::rect::RectF, bounds: pathfinder_geometry::rect::RectF,
_: &Self::LayoutState, _: &Self::LayoutState,
_: &Self::PaintState, _: &Self::PaintState,
view: &V,
cx: &ViewContext<V>, cx: &ViewContext<V>,
) -> json::Value { ) -> json::Value {
json!({ json!({

View File

@ -25,7 +25,7 @@ where
impl<V: View, F> Element<V> for Canvas<V, F> impl<V: View, F> Element<V> for Canvas<V, F>
where where
F: FnMut(RectF, RectF, &mut ViewContext<V>), F: FnMut(&mut SceneBuilder, RectF, RectF, &mut V, &mut ViewContext<V>),
{ {
type LayoutState = (); type LayoutState = ();
type PaintState = (); type PaintState = ();
@ -58,7 +58,7 @@ where
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
self.0(bounds, visible_bounds, cx) self.0(scene, bounds, visible_bounds, view, cx)
} }
fn rect_for_text_range( fn rect_for_text_range(

View File

@ -37,10 +37,10 @@ impl<V: View> Element<V> for Clipped<V> {
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
cx.scene.push_layer(Some(bounds)); scene.paint_layer(Some(bounds), |scene| {
self.child self.child
.paint(scene, bounds.origin(), visible_bounds, view, cx); .paint(scene, bounds.origin(), visible_bounds, view, cx)
cx.scene.pop_layer(); })
} }
fn rect_for_text_range( fn rect_for_text_range(

View File

@ -157,7 +157,7 @@ impl<V: View> Element<V> for ConstrainedBox<V> {
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
cx.paint_layer(Some(visible_bounds), |cx| { scene.paint_layer(Some(visible_bounds), |scene| {
self.child self.child
.paint(scene, bounds.origin(), visible_bounds, view, cx); .paint(scene, bounds.origin(), visible_bounds, view, cx);
}) })

View File

@ -221,7 +221,7 @@ impl<V: View> Element<V> for Container<V> {
); );
if let Some(shadow) = self.style.shadow.as_ref() { if let Some(shadow) = self.style.shadow.as_ref() {
cx.scene.push_shadow(scene::Shadow { scene.push_shadow(scene::Shadow {
bounds: quad_bounds + shadow.offset, bounds: quad_bounds + shadow.offset,
corner_radius: self.style.corner_radius, corner_radius: self.style.corner_radius,
sigma: shadow.blur, sigma: shadow.blur,
@ -231,7 +231,7 @@ impl<V: View> Element<V> for Container<V> {
if let Some(hit_bounds) = quad_bounds.intersection(visible_bounds) { if let Some(hit_bounds) = quad_bounds.intersection(visible_bounds) {
if let Some(style) = self.style.cursor { if let Some(style) = self.style.cursor {
cx.scene.push_cursor_region(CursorRegion { scene.push_cursor_region(CursorRegion {
bounds: hit_bounds, bounds: hit_bounds,
style, style,
}); });
@ -242,7 +242,7 @@ impl<V: View> Element<V> for Container<V> {
quad_bounds.origin() + vec2f(self.style.padding.left, self.style.padding.top); quad_bounds.origin() + vec2f(self.style.padding.left, self.style.padding.top);
if self.style.border.overlay { if self.style.border.overlay {
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: quad_bounds, bounds: quad_bounds,
background: self.style.background_color, background: self.style.background_color,
border: Default::default(), border: Default::default(),
@ -252,16 +252,16 @@ impl<V: View> Element<V> for Container<V> {
self.child self.child
.paint(scene, child_origin, visible_bounds, view, cx); .paint(scene, child_origin, visible_bounds, view, cx);
cx.scene.push_layer(None); scene.push_layer(None);
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: quad_bounds, bounds: quad_bounds,
background: self.style.overlay_color, background: self.style.overlay_color,
border: self.style.border, border: self.style.border,
corner_radius: self.style.corner_radius, corner_radius: self.style.corner_radius,
}); });
cx.scene.pop_layer(); scene.pop_layer();
} else { } else {
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: quad_bounds, bounds: quad_bounds,
background: self.style.background_color, background: self.style.background_color,
border: self.style.border, border: self.style.border,
@ -277,14 +277,14 @@ impl<V: View> Element<V> for Container<V> {
.paint(scene, child_origin, visible_bounds, view, cx); .paint(scene, child_origin, visible_bounds, view, cx);
if self.style.overlay_color.is_some() { if self.style.overlay_color.is_some() {
cx.scene.push_layer(None); scene.push_layer(None);
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: quad_bounds, bounds: quad_bounds,
background: self.style.overlay_color, background: self.style.overlay_color,
border: Default::default(), border: Default::default(),
corner_radius: 0., corner_radius: 0.,
}); });
cx.scene.pop_layer(); scene.pop_layer();
} }
} }
} }

View File

@ -33,7 +33,7 @@ impl<V: View> Element<V> for Empty {
fn layout( fn layout(
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
_: &V, _: &mut V,
_: &mut ViewContext<V>, _: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let x = if constraint.max.x().is_finite() && !self.collapsed { let x = if constraint.max.x().is_finite() && !self.collapsed {
@ -56,6 +56,7 @@ impl<V: View> Element<V> for Empty {
_: RectF, _: RectF,
_: RectF, _: RectF,
_: &mut Self::LayoutState, _: &mut Self::LayoutState,
_: &mut V,
_: &mut ViewContext<V>, _: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
} }

View File

@ -42,7 +42,7 @@ impl<V: View> Element<V> for Expanded<V> {
&mut self, &mut self,
mut constraint: SizeConstraint, mut constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
if self.full_width { if self.full_width {
constraint.min.set_x(constraint.max.x()); constraint.min.set_x(constraint.max.x());

View File

@ -73,7 +73,7 @@ impl<V: View> Flex<V> {
remaining_space: &mut f32, remaining_space: &mut f32,
remaining_flex: &mut f32, remaining_flex: &mut f32,
cross_axis_max: &mut f32, cross_axis_max: &mut f32,
view: &V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) { ) {
let cross_axis = self.axis.invert(); let cross_axis = self.axis.invert();
@ -124,7 +124,7 @@ impl<V: View> Element<V> for Flex<V> {
fn layout( fn layout(
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let mut total_flex = None; let mut total_flex = None;
@ -253,7 +253,7 @@ impl<V: View> Element<V> for Flex<V> {
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
remaining_space: &mut Self::LayoutState, remaining_space: &mut Self::LayoutState,
view: &V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
@ -261,16 +261,16 @@ impl<V: View> Element<V> for Flex<V> {
let mut remaining_space = *remaining_space; let mut remaining_space = *remaining_space;
let overflowing = remaining_space < 0.; let overflowing = remaining_space < 0.;
if overflowing { if overflowing {
cx.scene.push_layer(Some(visible_bounds)); scene.push_layer(Some(visible_bounds));
} }
if let Some(scroll_state) = &self.scroll_state { if let Some(scroll_state) = &self.scroll_state {
cx.scene.push_mouse_region( scene.push_mouse_region(
crate::MouseRegion::new::<Self>(scroll_state.1, 0, bounds) crate::MouseRegion::new::<Self>(scroll_state.1, 0, bounds)
.on_scroll({ .on_scroll({
let scroll_state = scroll_state.0.read(cx).clone(); let scroll_state = scroll_state.0.read(cx).clone();
let axis = self.axis; let axis = self.axis;
move |e, cx| { move |e, _: &mut V, cx| {
if remaining_space < 0. { if remaining_space < 0. {
let scroll_delta = e.delta.raw(); let scroll_delta = e.delta.raw();
@ -298,7 +298,7 @@ impl<V: View> Element<V> for Flex<V> {
} }
} }
}) })
.on_move(|_, _| { /* Capture move events */ }), .on_move(|_, _: &mut V, _| { /* Capture move events */ }),
) )
} }
@ -356,7 +356,7 @@ impl<V: View> Element<V> for Flex<V> {
} }
if overflowing { if overflowing {
cx.scene.pop_layer(); scene.pop_layer();
} }
} }
@ -372,7 +372,7 @@ impl<V: View> Element<V> for Flex<V> {
) -> Option<RectF> { ) -> Option<RectF> {
self.children self.children
.iter() .iter()
.find_map(|child| child.rect_for_text_range(view, range_utf16.clone(), cx)) .find_map(|child| child.rect_for_text_range(range_utf16.clone(), view, cx))
} }
fn debug( fn debug(
@ -431,7 +431,7 @@ impl<V: View> Element<V> for FlexItem<V> {
fn layout( fn layout(
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let size = self.child.layout(constraint, view, cx); let size = self.child.layout(constraint, view, cx);
@ -444,7 +444,7 @@ impl<V: View> Element<V> for FlexItem<V> {
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
_: &mut Self::LayoutState, _: &mut Self::LayoutState,
view: &V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
self.child self.child
@ -474,7 +474,6 @@ impl<V: View> Element<V> for FlexItem<V> {
_: &Self::LayoutState, _: &Self::LayoutState,
_: &Self::PaintState, _: &Self::PaintState,
view: &V, view: &V,
cx: &ViewContext<V>, cx: &ViewContext<V>,
) -> Value { ) -> Value {
json!({ json!({

View File

@ -35,7 +35,7 @@ impl<V: View> Element<V> for Hook<V> {
fn layout( fn layout(
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let size = self.child.layout(constraint, view, cx); let size = self.child.layout(constraint, view, cx);

View File

@ -62,7 +62,7 @@ impl<V: View> Element<V> for Image {
fn layout( fn layout(
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &V, _: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let data = match &self.source { let data = match &self.source {
@ -94,8 +94,8 @@ impl<V: View> Element<V> for Image {
bounds: RectF, bounds: RectF,
_: RectF, _: RectF,
layout: &mut Self::LayoutState, layout: &mut Self::LayoutState,
_: &V, _: &mut V,
cx: &mut ViewContext<V>, _: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
if let Some(data) = layout { if let Some(data) = layout {
scene.push_image(scene::Image { scene.push_image(scene::Image {

View File

@ -41,12 +41,11 @@ impl<V: View> Element<V> for KeystrokeLabel {
fn layout( fn layout(
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> (Vector2F, ElementBox<V>) { ) -> (Vector2F, ElementBox<V>) {
let mut element = if let Some(keystrokes) = let mut element = if let Some(keystrokes) =
cx.app cx.keystrokes_for_action(self.window_id, self.view_id, self.action.as_ref())
.keystrokes_for_action(self.window_id, self.view_id, self.action.as_ref())
{ {
Flex::row() Flex::row()
.with_children(keystrokes.iter().map(|keystroke| { .with_children(keystrokes.iter().map(|keystroke| {
@ -70,7 +69,7 @@ impl<V: View> Element<V> for KeystrokeLabel {
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
element: &mut ElementBox<V>, element: &mut ElementBox<V>,
view: &V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) { ) {
element.paint(scene, bounds.origin(), visible_bounds, view, cx); element.paint(scene, bounds.origin(), visible_bounds, view, cx);

View File

@ -134,13 +134,15 @@ impl<V: View> Element<V> for Label {
fn layout( fn layout(
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &V, _: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let runs = self.compute_runs(); let runs = self.compute_runs();
let line = let line = cx.text_layout_cache().layout_str(
cx.text_layout_cache &self.text,
.layout_str(&self.text, self.style.text.font_size, runs.as_slice()); self.style.text.font_size,
runs.as_slice(),
);
let size = vec2f( let size = vec2f(
line.width() line.width()
@ -159,8 +161,8 @@ impl<V: View> Element<V> for Label {
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
line: &mut Self::LayoutState, line: &mut Self::LayoutState,
_: &V, _: &mut V,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
line.paint( line.paint(
scene, scene,

View File

@ -13,7 +13,6 @@ pub struct List<V: View> {
state: ListState<V>, state: ListState<V>,
} }
#[derive(Clone)]
pub struct ListState<V: View>(Rc<RefCell<StateInner<V>>>); pub struct ListState<V: View>(Rc<RefCell<StateInner<V>>>);
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
@ -42,7 +41,7 @@ pub struct ListOffset {
enum ListItem<V: View> { enum ListItem<V: View> {
Unrendered, Unrendered,
Rendered(Rc<ElementBox<V>>), Rendered(Rc<RefCell<ElementBox<V>>>),
Removed(f32), Removed(f32),
} }
@ -145,7 +144,7 @@ impl<V: View> Element<V> for List<V> {
view, view,
cx, cx,
) { ) {
rendered_height += element.size().y(); rendered_height += element.borrow().size().y();
rendered_items.push_back(ListItem::Rendered(element)); rendered_items.push_back(ListItem::Rendered(element));
} }
} }
@ -162,7 +161,7 @@ impl<V: View> Element<V> for List<V> {
if let Some(element) = if let Some(element) =
state.render_item(cursor.start().0, None, item_constraint, view, cx) state.render_item(cursor.start().0, None, item_constraint, view, cx)
{ {
rendered_height += element.size().y(); rendered_height += element.borrow().size().y();
rendered_items.push_front(ListItem::Rendered(element)); rendered_items.push_front(ListItem::Rendered(element));
} }
} else { } else {
@ -198,7 +197,7 @@ impl<V: View> Element<V> for List<V> {
if let Some(element) = if let Some(element) =
state.render_item(cursor.start().0, Some(item), item_constraint, view, cx) state.render_item(cursor.start().0, Some(item), item_constraint, view, cx)
{ {
leading_overdraw += element.size().y(); leading_overdraw += element.borrow().size().y();
rendered_items.push_front(ListItem::Rendered(element)); rendered_items.push_front(ListItem::Rendered(element));
} }
} else { } else {
@ -264,12 +263,13 @@ impl<V: View> Element<V> for List<V> {
let state = self.state.clone(); let state = self.state.clone();
let height = bounds.height(); let height = bounds.height();
let scroll_top = scroll_top.clone(); let scroll_top = scroll_top.clone();
move |e, cx| { move |e, view, cx| {
state.0.borrow_mut().scroll( state.0.borrow_mut().scroll(
&scroll_top, &scroll_top,
height, height,
*e.platform_event.delta.raw(), *e.platform_event.delta.raw(),
e.platform_event.delta.precise(), e.platform_event.delta.precise(),
view,
cx, cx,
) )
} }
@ -277,8 +277,10 @@ impl<V: View> Element<V> for List<V> {
); );
let state = &mut *self.state.0.borrow_mut(); let state = &mut *self.state.0.borrow_mut();
for (mut element, origin) in state.visible_elements(bounds, scroll_top) { for (element, origin) in state.visible_elements(bounds, scroll_top) {
element.paint(scene, origin, visible_bounds, view, cx); element
.borrow_mut()
.paint(scene, origin, visible_bounds, view, cx);
} }
scene.pop_layer(); scene.pop_layer();
@ -304,11 +306,15 @@ impl<V: View> Element<V> for List<V> {
} }
if let ListItem::Rendered(element) = item { if let ListItem::Rendered(element) = item {
if let Some(rect) = element.rect_for_text_range(range_utf16.clone(), view, cx) { if let Some(rect) =
element
.borrow()
.rect_for_text_range(range_utf16.clone(), view, cx)
{
return Some(rect); return Some(rect);
} }
item_origin.set_y(item_origin.y() + element.size().y()); item_origin.set_y(item_origin.y() + element.borrow().size().y());
cursor.next(&()); cursor.next(&());
} else { } else {
unreachable!(); unreachable!();
@ -329,7 +335,7 @@ impl<V: View> Element<V> for List<V> {
let state = self.state.0.borrow_mut(); let state = self.state.0.borrow_mut();
let visible_elements = state let visible_elements = state
.visible_elements(bounds, scroll_top) .visible_elements(bounds, scroll_top)
.map(|e| e.0.debug(view, cx)) .map(|e| e.0.borrow().debug(view, cx))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let visible_range = scroll_top.item_ix..(scroll_top.item_ix + visible_elements.len()); let visible_range = scroll_top.item_ix..(scroll_top.item_ix + visible_elements.len());
json!({ json!({
@ -345,8 +351,7 @@ impl<V: View> ListState<V> {
element_count: usize, element_count: usize,
orientation: Orientation, orientation: Orientation,
overdraw: f32, overdraw: f32,
cx: &mut ViewContext<V>, render_item: F,
mut render_item: F,
) -> Self ) -> Self
where where
V: View, V: View,
@ -354,14 +359,9 @@ impl<V: View> ListState<V> {
{ {
let mut items = SumTree::new(); let mut items = SumTree::new();
items.extend((0..element_count).map(|_| ListItem::Unrendered), &()); items.extend((0..element_count).map(|_| ListItem::Unrendered), &());
let handle = cx.weak_handle();
Self(Rc::new(RefCell::new(StateInner { Self(Rc::new(RefCell::new(StateInner {
last_layout_width: None, last_layout_width: None,
render_item: Box::new(move |ix, view, cx| { render_item: Box::new(render_item),
render_item(view, ix, cx)
// let handle = handle.upgrade(cx)?;
// Some(cx.render(&handle, |view, cx| render_item(view, ix, cx)))
}),
rendered_range: 0..0, rendered_range: 0..0,
items, items,
logical_scroll_top: None, logical_scroll_top: None,
@ -439,6 +439,12 @@ impl<V: View> ListState<V> {
} }
} }
impl<V: View> Clone for ListState<V> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<V: View> StateInner<V> { impl<V: View> StateInner<V> {
fn render_item( fn render_item(
&mut self, &mut self,
@ -447,13 +453,13 @@ impl<V: View> StateInner<V> {
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Option<Rc<ElementBox<V>>> { ) -> Option<Rc<RefCell<ElementBox<V>>>> {
if let Some(ListItem::Rendered(element)) = existing_element { if let Some(ListItem::Rendered(element)) = existing_element {
Some(element.clone()) Some(element.clone())
} else { } else {
let mut element = (self.render_item)(view, ix, cx); let mut element = (self.render_item)(view, ix, cx);
element.layout(constraint, view, cx); element.layout(constraint, view, cx);
Some(element.into()) Some(Rc::new(RefCell::new(element)))
} }
} }
@ -469,7 +475,7 @@ impl<V: View> StateInner<V> {
&'a self, &'a self,
bounds: RectF, bounds: RectF,
scroll_top: &ListOffset, scroll_top: &ListOffset,
) -> impl Iterator<Item = (Rc<ElementBox<V>>, Vector2F)> + 'a { ) -> impl Iterator<Item = (Rc<RefCell<ElementBox<V>>>, Vector2F)> + 'a {
let mut item_origin = bounds.origin() - vec2f(0., scroll_top.offset_in_item); let mut item_origin = bounds.origin() - vec2f(0., scroll_top.offset_in_item);
let mut cursor = self.items.cursor::<Count>(); let mut cursor = self.items.cursor::<Count>();
cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &()); cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &());
@ -481,7 +487,7 @@ impl<V: View> StateInner<V> {
if let ListItem::Rendered(element) = item { if let ListItem::Rendered(element) = item {
let result = (element.clone(), item_origin); let result = (element.clone(), item_origin);
item_origin.set_y(item_origin.y() + element.size().y()); item_origin.set_y(item_origin.y() + element.borrow().size().y());
cursor.next(&()); cursor.next(&());
return Some(result); return Some(result);
} }
@ -526,7 +532,7 @@ impl<V: View> StateInner<V> {
if self.scroll_handler.is_some() { if self.scroll_handler.is_some() {
let visible_range = self.visible_range(height, scroll_top); let visible_range = self.visible_range(height, scroll_top);
self.scroll_handler.as_mut().unwrap()(visible_range, cx); self.scroll_handler.as_mut().unwrap()(visible_range, view, cx);
} }
cx.notify(); cx.notify();
@ -557,7 +563,7 @@ impl<V: View> ListItem<V> {
fn remove(&self) -> Self { fn remove(&self) -> Self {
match self { match self {
ListItem::Unrendered => ListItem::Unrendered, ListItem::Unrendered => ListItem::Unrendered,
ListItem::Rendered(element) => ListItem::Removed(element.size().y()), ListItem::Rendered(element) => ListItem::Removed(element.borrow().size().y()),
ListItem::Removed(height) => ListItem::Removed(*height), ListItem::Removed(height) => ListItem::Removed(*height),
} }
} }
@ -578,7 +584,7 @@ impl<V: View> sum_tree::Item for ListItem<V> {
count: 1, count: 1,
rendered_count: 1, rendered_count: 1,
unrendered_count: 0, unrendered_count: 0,
height: element.size().y(), height: element.borrow().size().y(),
}, },
ListItem::Removed(height) => ListItemSummary { ListItem::Removed(height) => ListItemSummary {
count: 1, count: 1,
@ -642,7 +648,6 @@ mod tests {
use super::*; use super::*;
use crate::{elements::Empty, geometry::vector::vec2f, Entity}; use crate::{elements::Empty, geometry::vector::vec2f, Entity};
use rand::prelude::*; use rand::prelude::*;
use std::env;
#[crate::test(self)] #[crate::test(self)]
fn test_layout(cx: &mut crate::AppContext) { fn test_layout(cx: &mut crate::AppContext) {

View File

@ -7,8 +7,8 @@ use crate::{
platform::CursorStyle, platform::CursorStyle,
platform::MouseButton, platform::MouseButton,
scene::{ scene::{
CursorRegion, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseHover, CursorRegion, EventContext, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag,
MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut,
}, },
Element, ElementBox, MouseRegion, MouseState, SceneBuilder, SizeConstraint, View, ViewContext, Element, ElementBox, MouseRegion, MouseState, SceneBuilder, SizeConstraint, View, ViewContext,
}; };
@ -31,13 +31,13 @@ pub struct MouseEventHandler<Tag: 'static, V: View> {
/// Element which provides a render_child callback with a MouseState and paints a mouse /// Element which provides a render_child callback with a MouseState and paints a mouse
/// region under (or above) it for easy mouse event handling. /// region under (or above) it for easy mouse event handling.
impl<Tag, V: View> MouseEventHandler<Tag, V> { impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn new<F>(region_id: usize, view: &mut V, cx: &mut ViewContext<V>, render_child: F) -> Self pub fn new<F>(region_id: usize, cx: &mut ViewContext<V>, render_child: F) -> Self
where where
V: View, V: View,
F: FnOnce(&mut MouseState, &mut V, &mut ViewContext<V>) -> ElementBox<V>, F: FnOnce(&mut MouseState, &mut ViewContext<V>) -> ElementBox<V>,
{ {
let mut mouse_state = cx.mouse_state::<Tag>(region_id); let mut mouse_state = cx.mouse_state::<Tag>(region_id);
let child = render_child(&mut mouse_state, view, cx); let child = render_child(&mut mouse_state, cx);
let notify_on_hover = mouse_state.accessed_hovered(); let notify_on_hover = mouse_state.accessed_hovered();
let notify_on_click = mouse_state.accessed_clicked(); let notify_on_click = mouse_state.accessed_clicked();
Self { Self {
@ -57,17 +57,12 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
/// Modifies the MouseEventHandler to render the MouseRegion above the child element. Useful /// Modifies the MouseEventHandler to render the MouseRegion above the child element. Useful
/// for drag and drop handling and similar events which should be captured before the child /// for drag and drop handling and similar events which should be captured before the child
/// gets the opportunity /// gets the opportunity
pub fn above<F>( pub fn above<F>(region_id: usize, cx: &mut ViewContext<V>, render_child: F) -> Self
region_id: usize,
view: &mut V,
cx: &mut ViewContext<V>,
render_child: F,
) -> Self
where where
V: View, V: View,
F: FnOnce(&mut MouseState, &mut V, &mut ViewContext<V>) -> ElementBox<V>, F: FnOnce(&mut MouseState, &mut ViewContext<V>) -> ElementBox<V>,
{ {
let mut handler = Self::new(region_id, view, cx, render_child); let mut handler = Self::new(region_id, cx, render_child);
handler.above = true; handler.above = true;
handler handler
} }
@ -82,14 +77,17 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
self self
} }
pub fn on_move(mut self, handler: impl Fn(MouseMove, &mut ViewContext<V>) + 'static) -> Self { pub fn on_move(
mut self,
handler: impl Fn(MouseMove, &mut V, &mut EventContext<V>) + 'static,
) -> Self {
self.handlers = self.handlers.on_move(handler); self.handlers = self.handlers.on_move(handler);
self self
} }
pub fn on_move_out( pub fn on_move_out(
mut self, mut self,
handler: impl Fn(MouseMoveOut, &mut ViewContext<V>) + 'static, handler: impl Fn(MouseMoveOut, &mut V, &mut EventContext<V>) + 'static,
) -> Self { ) -> Self {
self.handlers = self.handlers.on_move_out(handler); self.handlers = self.handlers.on_move_out(handler);
self self
@ -98,7 +96,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_down( pub fn on_down(
mut self, mut self,
button: MouseButton, button: MouseButton,
handler: impl Fn(MouseDown, &mut ViewContext<V>) + 'static, handler: impl Fn(MouseDown, &mut V, &mut EventContext<V>) + 'static,
) -> Self { ) -> Self {
self.handlers = self.handlers.on_down(button, handler); self.handlers = self.handlers.on_down(button, handler);
self self
@ -107,7 +105,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_up( pub fn on_up(
mut self, mut self,
button: MouseButton, button: MouseButton,
handler: impl Fn(MouseUp, &mut ViewContext<V>) + 'static, handler: impl Fn(MouseUp, &mut V, &mut EventContext<V>) + 'static,
) -> Self { ) -> Self {
self.handlers = self.handlers.on_up(button, handler); self.handlers = self.handlers.on_up(button, handler);
self self
@ -116,7 +114,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_click( pub fn on_click(
mut self, mut self,
button: MouseButton, button: MouseButton,
handler: impl Fn(MouseClick, &mut ViewContext<V>) + 'static, handler: impl Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
) -> Self { ) -> Self {
self.handlers = self.handlers.on_click(button, handler); self.handlers = self.handlers.on_click(button, handler);
self self
@ -125,7 +123,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_down_out( pub fn on_down_out(
mut self, mut self,
button: MouseButton, button: MouseButton,
handler: impl Fn(MouseDownOut, &mut ViewContext<V>) + 'static, handler: impl Fn(MouseDownOut, &mut V, &mut EventContext<V>) + 'static,
) -> Self { ) -> Self {
self.handlers = self.handlers.on_down_out(button, handler); self.handlers = self.handlers.on_down_out(button, handler);
self self
@ -134,7 +132,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_up_out( pub fn on_up_out(
mut self, mut self,
button: MouseButton, button: MouseButton,
handler: impl Fn(MouseUpOut, &mut ViewContext<V>) + 'static, handler: impl Fn(MouseUpOut, &mut V, &mut EventContext<V>) + 'static,
) -> Self { ) -> Self {
self.handlers = self.handlers.on_up_out(button, handler); self.handlers = self.handlers.on_up_out(button, handler);
self self
@ -143,20 +141,23 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_drag( pub fn on_drag(
mut self, mut self,
button: MouseButton, button: MouseButton,
handler: impl Fn(MouseDrag, &mut ViewContext<V>) + 'static, handler: impl Fn(MouseDrag, &mut V, &mut EventContext<V>) + 'static,
) -> Self { ) -> Self {
self.handlers = self.handlers.on_drag(button, handler); self.handlers = self.handlers.on_drag(button, handler);
self self
} }
pub fn on_hover(mut self, handler: impl Fn(MouseHover, &mut ViewContext<V>) + 'static) -> Self { pub fn on_hover(
mut self,
handler: impl Fn(MouseHover, &mut V, &mut EventContext<V>) + 'static,
) -> Self {
self.handlers = self.handlers.on_hover(handler); self.handlers = self.handlers.on_hover(handler);
self self
} }
pub fn on_scroll( pub fn on_scroll(
mut self, mut self,
handler: impl Fn(MouseScrollWheel, &mut ViewContext<V>) + 'static, handler: impl Fn(MouseScrollWheel, &mut V, &mut EventContext<V>) + 'static,
) -> Self { ) -> Self {
self.handlers = self.handlers.on_scroll(handler); self.handlers = self.handlers.on_scroll(handler);
self self
@ -191,14 +192,14 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
let hit_bounds = self.hit_bounds(visible_bounds); let hit_bounds = self.hit_bounds(visible_bounds);
if let Some(style) = self.cursor_style { if let Some(style) = self.cursor_style {
cx.scene.push_cursor_region(CursorRegion { scene.push_cursor_region(CursorRegion {
bounds: hit_bounds, bounds: hit_bounds,
style, style,
}); });
} }
cx.scene.push_mouse_region( scene.push_mouse_region(
MouseRegion::from_handlers::<Tag>( MouseRegion::from_handlers::<Tag>(
cx.current_view_id(), cx.view_id(),
self.region_id, self.region_id,
hit_bounds, hit_bounds,
self.handlers.clone(), self.handlers.clone(),
@ -236,7 +237,7 @@ impl<Tag, V: View> Element<V> for MouseEventHandler<Tag, V> {
self.child self.child
.paint(scene, bounds.origin(), visible_bounds, view, cx); .paint(scene, bounds.origin(), visible_bounds, view, cx);
cx.paint_layer(None, |cx| { scene.paint_layer(None, |scene| {
self.paint_regions(scene, bounds, visible_bounds, cx); self.paint_regions(scene, bounds, visible_bounds, cx);
}); });
} else { } else {
@ -254,7 +255,7 @@ impl<Tag, V: View> Element<V> for MouseEventHandler<Tag, V> {
_: &Self::LayoutState, _: &Self::LayoutState,
_: &Self::PaintState, _: &Self::PaintState,
view: &V, view: &V,
cx: &ViewContext<Self>, cx: &ViewContext<V>,
) -> Option<RectF> { ) -> Option<RectF> {
self.child.rect_for_text_range(range_utf16, view, cx) self.child.rect_for_text_range(range_utf16, view, cx)
} }

View File

@ -127,7 +127,7 @@ impl<V: View> Element<V> for Overlay<V> {
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let constraint = if self.anchor_position.is_some() { let constraint = if self.anchor_position.is_some() {
SizeConstraint::new(Vector2F::zero(), cx.window_size) SizeConstraint::new(Vector2F::zero(), cx.window_size())
} else { } else {
constraint constraint
}; };
@ -137,7 +137,7 @@ impl<V: View> Element<V> for Overlay<V> {
fn paint( fn paint(
&mut self, &mut self,
scene: SceneBuilder, scene: &mut SceneBuilder,
bounds: RectF, bounds: RectF,
_: RectF, _: RectF,
size: &mut Self::LayoutState, size: &mut Self::LayoutState,
@ -163,9 +163,9 @@ impl<V: View> Element<V> for Overlay<V> {
OverlayFitMode::SnapToWindow => { OverlayFitMode::SnapToWindow => {
// Snap the horizontal edges of the overlay to the horizontal edges of the window if // Snap the horizontal edges of the overlay to the horizontal edges of the window if
// its horizontal bounds overflow // its horizontal bounds overflow
if bounds.max_x() > cx.window_size.x() { if bounds.max_x() > cx.window_size().x() {
let mut lower_right = bounds.lower_right(); let mut lower_right = bounds.lower_right();
lower_right.set_x(cx.window_size.x()); lower_right.set_x(cx.window_size().x());
bounds = RectF::from_points(lower_right - *size, lower_right); bounds = RectF::from_points(lower_right - *size, lower_right);
} else if bounds.min_x() < 0. { } else if bounds.min_x() < 0. {
let mut upper_left = bounds.origin(); let mut upper_left = bounds.origin();
@ -175,9 +175,9 @@ impl<V: View> Element<V> for Overlay<V> {
// Snap the vertical edges of the overlay to the vertical edges of the window if // Snap the vertical edges of the overlay to the vertical edges of the window if
// its vertical bounds overflow. // its vertical bounds overflow.
if bounds.max_y() > cx.window_size.y() { if bounds.max_y() > cx.window_size().y() {
let mut lower_right = bounds.lower_right(); let mut lower_right = bounds.lower_right();
lower_right.set_y(cx.window_size.y()); lower_right.set_y(cx.window_size().y());
bounds = RectF::from_points(lower_right - *size, lower_right); bounds = RectF::from_points(lower_right - *size, lower_right);
} else if bounds.min_y() < 0. { } else if bounds.min_y() < 0. {
let mut upper_left = bounds.origin(); let mut upper_left = bounds.origin();
@ -188,11 +188,11 @@ impl<V: View> Element<V> for Overlay<V> {
OverlayFitMode::SwitchAnchor => { OverlayFitMode::SwitchAnchor => {
let mut anchor_corner = self.anchor_corner; let mut anchor_corner = self.anchor_corner;
if bounds.max_x() > cx.window_size.x() { if bounds.max_x() > cx.window_size().x() {
anchor_corner = anchor_corner.switch_axis(Axis::Horizontal); anchor_corner = anchor_corner.switch_axis(Axis::Horizontal);
} }
if bounds.max_y() > cx.window_size.y() { if bounds.max_y() > cx.window_size().y() {
anchor_corner = anchor_corner.switch_axis(Axis::Vertical); anchor_corner = anchor_corner.switch_axis(Axis::Vertical);
} }
@ -212,14 +212,13 @@ impl<V: View> Element<V> for Overlay<V> {
OverlayFitMode::None => {} OverlayFitMode::None => {}
} }
cx.paint_stacking_context(None, self.z_index, |cx| { scene.paint_stacking_context(None, self.z_index, |scene| {
if self.hoverable { if self.hoverable {
enum OverlayHoverCapture {} enum OverlayHoverCapture {}
// Block hovers in lower stacking contexts // Block hovers in lower stacking contexts
cx.scene scene.push_mouse_region(MouseRegion::new::<OverlayHoverCapture>(
.push_mouse_region(MouseRegion::new::<OverlayHoverCapture>( cx.view_id(),
cx.current_view_id(), cx.view_id(),
cx.current_view_id(),
bounds, bounds,
)); ));
} }
@ -227,7 +226,7 @@ impl<V: View> Element<V> for Overlay<V> {
self.child.paint( self.child.paint(
scene, scene,
bounds.origin(), bounds.origin(),
RectF::new(Vector2F::zero(), cx.window_size), RectF::new(Vector2F::zero(), cx.window_size()),
view, view,
cx, cx,
); );

View File

@ -154,22 +154,18 @@ impl<V: View> Element<V> for Resizable<V> {
view: &mut V, view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
cx.scene.push_stacking_context(None, None); scene.push_stacking_context(None, None);
let handle_region = self.side.of_rect(bounds, self.handle_size); let handle_region = self.side.of_rect(bounds, self.handle_size);
enum ResizeHandle {} enum ResizeHandle {}
cx.scene.push_mouse_region( scene.push_mouse_region(
MouseRegion::new::<ResizeHandle>( MouseRegion::new::<ResizeHandle>(cx.view_id(), self.side as usize, handle_region)
cx.current_view_id(), .on_down(MouseButton::Left, |_, _: &mut V, _| {}) // This prevents the mouse down event from being propagated elsewhere
self.side as usize,
handle_region,
)
.on_down(MouseButton::Left, |_, _| {}) // This prevents the mouse down event from being propagated elsewhere
.on_drag(MouseButton::Left, { .on_drag(MouseButton::Left, {
let state = self.state.clone(); let state = self.state.clone();
let side = self.side; let side = self.side;
move |e, cx| { move |e, _: &mut V, cx| {
let prev_width = state.actual_dimension.get(); let prev_width = state.actual_dimension.get();
state state
.custom_dimension .custom_dimension
@ -179,7 +175,7 @@ impl<V: View> Element<V> for Resizable<V> {
}), }),
); );
cx.scene.push_cursor_region(crate::CursorRegion { scene.push_cursor_region(crate::CursorRegion {
bounds: handle_region, bounds: handle_region,
style: match self.side.axis() { style: match self.side.axis() {
Axis::Horizontal => CursorStyle::ResizeLeftRight, Axis::Horizontal => CursorStyle::ResizeLeftRight,
@ -187,7 +183,7 @@ impl<V: View> Element<V> for Resizable<V> {
}, },
}); });
cx.scene.pop_stacking_context(); scene.pop_stacking_context();
self.child self.child
.paint(scene, bounds.origin(), visible_bounds, view, cx); .paint(scene, bounds.origin(), visible_bounds, view, cx);

View File

@ -8,11 +8,18 @@ use crate::{
/// Element which renders it's children in a stack on top of each other. /// Element which renders it's children in a stack on top of each other.
/// The first child determines the size of the others. /// The first child determines the size of the others.
#[derive(Default)]
pub struct Stack<V: View> { pub struct Stack<V: View> {
children: Vec<ElementBox<V>>, children: Vec<ElementBox<V>>,
} }
impl<V: View> Default for Stack<V> {
fn default() -> Self {
Self {
children: Vec::new(),
}
}
}
impl<V: View> Stack<V> { impl<V: View> Stack<V> {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
@ -53,7 +60,7 @@ impl<V: View> Element<V> for Stack<V> {
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
for child in &mut self.children { for child in &mut self.children {
cx.paint_layer(None, |cx| { scene.paint_layer(None, |scene| {
child.paint(scene, bounds.origin(), visible_bounds, view, cx); child.paint(scene, bounds.origin(), visible_bounds, view, cx);
}); });
} }

View File

@ -37,7 +37,7 @@ impl<V: View> Element<V> for Svg {
fn layout( fn layout(
&mut self, &mut self,
constraint: SizeConstraint, constraint: SizeConstraint,
view: &mut V, _: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
match cx.asset_cache.svg(&self.path) { match cx.asset_cache.svg(&self.path) {

View File

@ -98,7 +98,7 @@ impl<V: View> Element<V> for Text {
let shaped_lines = layout_highlighted_chunks( let shaped_lines = layout_highlighted_chunks(
chunks, chunks,
&self.style, &self.style,
cx.text_layout_cache, cx.text_layout_cache(),
&cx.font_cache, &cx.font_cache,
usize::MAX, usize::MAX,
self.text.matches('\n').count() + 1, self.text.matches('\n').count() + 1,
@ -213,9 +213,9 @@ impl<V: View> Element<V> for Text {
/// Perform text layout on a series of highlighted chunks of text. /// Perform text layout on a series of highlighted chunks of text.
pub fn layout_highlighted_chunks<'a>( pub fn layout_highlighted_chunks<'a>(
chunks: impl Iterator<Item = (&'a str, Option<HighlightStyle>)>, chunks: impl Iterator<Item = (&'a str, Option<HighlightStyle>)>,
text_style: &'a TextStyle, text_style: &TextStyle,
text_layout_cache: &'a TextLayoutCache, text_layout_cache: &TextLayoutCache,
font_cache: &'a Arc<FontCache>, font_cache: &Arc<FontCache>,
max_line_len: usize, max_line_len: usize,
max_line_count: usize, max_line_count: usize,
) -> Vec<Line> { ) -> Vec<Line> {
@ -276,27 +276,23 @@ pub fn layout_highlighted_chunks<'a>(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::{ use crate::{elements::Empty, fonts, AppContext, ElementBox, Entity, View, ViewContext};
elements::Empty, fonts, platform, AppContext, ElementBox, Entity, View, ViewContext,
};
#[crate::test(self)] #[crate::test(self)]
fn test_soft_wrapping_with_carriage_returns(cx: &mut AppContext) { fn test_soft_wrapping_with_carriage_returns(cx: &mut AppContext) {
let (window_id, root_view) = cx.add_window(Default::default(), |_| TestView); let (window_id, root_view) = cx.add_window(Default::default(), |_| TestView);
let mut presenter = cx.build_window(
window_id,
root_view.into_any(),
Box::new(platform::test::Window::new(Vector2F::new(800., 600.))),
);
fonts::with_font_cache(cx.font_cache().clone(), || { fonts::with_font_cache(cx.font_cache().clone(), || {
root_view.update(cx, |view, cx| {
let mut text = Text::new("Hello\r\n", Default::default()).with_soft_wrap(true); let mut text = Text::new("Hello\r\n", Default::default()).with_soft_wrap(true);
let (_, state) = text.layout( let (_, state) = text.layout(
SizeConstraint::new(Default::default(), vec2f(f32::INFINITY, f32::INFINITY)), SizeConstraint::new(Default::default(), vec2f(f32::INFINITY, f32::INFINITY)),
&mut presenter.build_layout_context(Default::default(), false, cx), view,
cx,
); );
assert_eq!(state.shaped_lines.len(), 2); assert_eq!(state.shaped_lines.len(), 2);
assert_eq!(state.wrap_boundaries.len(), 2); assert_eq!(state.wrap_boundaries.len(), 2);
}); });
});
} }
struct TestView; struct TestView;

View File

@ -55,7 +55,6 @@ impl<V: View> Tooltip<V> {
action: Option<Box<dyn Action>>, action: Option<Box<dyn Action>>,
style: TooltipStyle, style: TooltipStyle,
child: ElementBox<V>, child: ElementBox<V>,
view: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self { ) -> Self {
struct ElementState<Tag>(Tag); struct ElementState<Tag>(Tag);
@ -78,10 +77,10 @@ impl<V: View> Tooltip<V> {
Overlay::new( Overlay::new(
Self::render_tooltip(cx.window_id, focused_view_id, text, style, action, false) Self::render_tooltip(cx.window_id, focused_view_id, text, style, action, false)
.constrained() .constrained()
.dynamically(move |constraint, cx| { .dynamically(move |constraint, view, cx| {
SizeConstraint::strict_along( SizeConstraint::strict_along(
Axis::Vertical, Axis::Vertical,
collapsed_tooltip.layout(constraint, cx).y(), collapsed_tooltip.layout(constraint, view, cx).y(),
) )
}) })
.boxed(), .boxed(),
@ -93,12 +92,11 @@ impl<V: View> Tooltip<V> {
} else { } else {
None None
}; };
let child = let child = MouseEventHandler::<MouseEventHandlerState<Tag>, _>::new(id, cx, |_, _| child)
MouseEventHandler::<MouseEventHandlerState<Tag>>::new(id, view, cx, |_, _| child) .on_hover(move |e, _, cx| {
.on_hover(move |e, cx| {
let position = e.position; let position = e.position;
let window_id = cx.window_id(); let window_id = cx.window_id();
if let Some(view_id) = cx.view_id() { let view_id = cx.view_id();
if e.started { if e.started {
if !state.visible.get() { if !state.visible.get() {
state.position.set(position); state.position.set(position);
@ -107,7 +105,7 @@ impl<V: View> Tooltip<V> {
if debounce.is_none() { if debounce.is_none() {
*debounce = Some(cx.spawn({ *debounce = Some(cx.spawn({
let state = state.clone(); let state = state.clone();
|mut cx| async move { |_, mut cx| async move {
cx.background().timer(DEBOUNCE_TIMEOUT).await; cx.background().timer(DEBOUNCE_TIMEOUT).await;
state.visible.set(true); state.visible.set(true);
cx.update(|cx| cx.notify_view(window_id, view_id)); cx.update(|cx| cx.notify_view(window_id, view_id));
@ -120,7 +118,6 @@ impl<V: View> Tooltip<V> {
state.debounce.take(); state.debounce.take();
cx.notify(); cx.notify();
} }
}
}) })
.boxed(); .boxed();
Self { Self {
@ -137,7 +134,7 @@ impl<V: View> Tooltip<V> {
style: TooltipStyle, style: TooltipStyle,
action: Option<Box<dyn Action>>, action: Option<Box<dyn Action>>,
measure: bool, measure: bool,
) -> impl Element { ) -> impl Element<V> {
Flex::row() Flex::row()
.with_child({ .with_child({
let text = Text::new(text, style.text) let text = Text::new(text, style.text)
@ -181,7 +178,7 @@ impl<V: View> Element<V> for Tooltip<V> {
let size = self.child.layout(constraint, view, cx); let size = self.child.layout(constraint, view, cx);
if let Some(tooltip) = self.tooltip.as_mut() { if let Some(tooltip) = self.tooltip.as_mut() {
tooltip.layout( tooltip.layout(
SizeConstraint::new(Vector2F::zero(), cx.window_size), SizeConstraint::new(Vector2F::zero(), cx.window_size()),
view, view,
cx, cx,
); );

View File

@ -6,7 +6,6 @@ use crate::{
}, },
json::{self, json}, json::{self, json},
platform::ScrollWheelEvent, platform::ScrollWheelEvent,
scene::MouseScrollWheel,
ElementBox, MouseRegion, SceneBuilder, View, ViewContext, ElementBox, MouseRegion, SceneBuilder, View, ViewContext,
}; };
use json::ToJson; use json::ToJson;
@ -47,7 +46,7 @@ pub struct UniformList<V: View> {
state: UniformListState, state: UniformListState,
item_count: usize, item_count: usize,
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
append_items: Box<dyn Fn(Range<usize>, &mut Vec<ElementBox<V>>, &mut V, &mut ViewContext<V>)>, append_items: Box<dyn Fn(&mut V, Range<usize>, &mut Vec<ElementBox<V>>, &mut ViewContext<V>)>,
padding_top: f32, padding_top: f32,
padding_bottom: f32, padding_bottom: f32,
get_width_from_item: Option<usize>, get_width_from_item: Option<usize>,
@ -63,19 +62,12 @@ impl<V: View> UniformList<V> {
) -> Self ) -> Self
where where
V: View, V: View,
F: 'static + Fn(&mut V, Range<usize>, &mut Vec<ElementBox<V>>, &mut V, &mut ViewContext<V>), F: 'static + Fn(&mut V, Range<usize>, &mut Vec<ElementBox<V>>, &mut ViewContext<V>),
{ {
let handle = cx.handle();
Self { Self {
state, state,
item_count, item_count,
append_items: Box::new(move |range, items, cx| { append_items: Box::new(append_items),
if let Some(handle) = handle.upgrade(cx) {
cx.render(&handle, |view, cx| {
append_items(view, range, items, cx);
});
}
}),
padding_top: 0., padding_top: 0.,
padding_bottom: 0., padding_bottom: 0.,
get_width_from_item: None, get_width_from_item: None,
@ -194,18 +186,18 @@ impl<V: View> Element<V> for UniformList<V> {
let sample_item_ix; let sample_item_ix;
let sample_item; let sample_item;
if let Some(sample_ix) = self.get_width_from_item { if let Some(sample_ix) = self.get_width_from_item {
(self.append_items)(sample_ix..sample_ix + 1, &mut items, cx); (self.append_items)(view, sample_ix..sample_ix + 1, &mut items, cx);
sample_item_ix = sample_ix; sample_item_ix = sample_ix;
if let Some(mut item) = items.pop() { if let Some(mut item) = items.pop() {
item_size = item.layout(constraint, cx); item_size = item.layout(constraint, view, cx);
size.set_x(item_size.x()); size.set_x(item_size.x());
sample_item = item; sample_item = item;
} else { } else {
return no_items; return no_items;
} }
} else { } else {
(self.append_items)(0..1, &mut items, cx); (self.append_items)(view, 0..1, &mut items, cx);
sample_item_ix = 0; sample_item_ix = 0;
if let Some(mut item) = items.pop() { if let Some(mut item) = items.pop() {
item_size = item.layout( item_size = item.layout(
@ -213,6 +205,7 @@ impl<V: View> Element<V> for UniformList<V> {
vec2f(constraint.max.x(), 0.0), vec2f(constraint.max.x(), 0.0),
vec2f(constraint.max.x(), f32::INFINITY), vec2f(constraint.max.x(), f32::INFINITY),
), ),
view,
cx, cx,
); );
item_size.set_x(size.x()); item_size.set_x(size.x());
@ -249,16 +242,16 @@ impl<V: View> Element<V> for UniformList<V> {
if (start..end).contains(&sample_item_ix) { if (start..end).contains(&sample_item_ix) {
if sample_item_ix > start { if sample_item_ix > start {
(self.append_items)(start..sample_item_ix, &mut items, cx); (self.append_items)(view, start..sample_item_ix, &mut items, cx);
} }
items.push(sample_item); items.push(sample_item);
if sample_item_ix < end { if sample_item_ix < end {
(self.append_items)(sample_item_ix + 1..end, &mut items, cx); (self.append_items)(view, sample_item_ix + 1..end, &mut items, cx);
} }
} else { } else {
(self.append_items)(start..end, &mut items, cx); (self.append_items)(view, start..end, &mut items, cx);
} }
for item in &mut items { for item in &mut items {
@ -289,20 +282,16 @@ impl<V: View> Element<V> for UniformList<V> {
) -> Self::PaintState { ) -> Self::PaintState {
let visible_bounds = visible_bounds.intersection(bounds).unwrap_or_default(); let visible_bounds = visible_bounds.intersection(bounds).unwrap_or_default();
cx.scene.push_layer(Some(visible_bounds)); scene.push_layer(Some(visible_bounds));
cx.scene.push_mouse_region( scene.push_mouse_region(
MouseRegion::new::<Self>(self.view_id, 0, visible_bounds).on_scroll({ MouseRegion::new::<Self>(self.view_id, 0, visible_bounds).on_scroll({
let scroll_max = layout.scroll_max; let scroll_max = layout.scroll_max;
let state = self.state.clone(); let state = self.state.clone();
move |MouseScrollWheel { move |event, _, cx| {
platform_event: let ScrollWheelEvent {
ScrollWheelEvent {
position, delta, .. position, delta, ..
}, } = event.platform_event;
..
},
cx| {
if !Self::scroll( if !Self::scroll(
state.clone(), state.clone(),
position, position,
@ -328,7 +317,7 @@ impl<V: View> Element<V> for UniformList<V> {
item_origin += vec2f(0.0, layout.item_height); item_origin += vec2f(0.0, layout.item_height);
} }
cx.scene.pop_layer(); scene.pop_layer();
} }
fn rect_for_text_range( fn rect_for_text_range(

View File

@ -15,7 +15,9 @@ pub use clipboard::ClipboardItem;
pub mod fonts; pub mod fonts;
pub mod geometry; pub mod geometry;
pub mod scene; pub mod scene;
pub use scene::{Border, CursorRegion, MouseRegion, MouseRegionId, Quad, Scene, SceneBuilder}; pub use scene::{
Border, CursorRegion, EventContext, MouseRegion, MouseRegionId, Quad, Scene, SceneBuilder,
};
pub mod text_layout; pub mod text_layout;
pub use text_layout::TextLayoutCache; pub use text_layout::TextLayoutCache;
mod util; mod util;

View File

@ -236,6 +236,19 @@ impl SceneBuilder {
self.scale_factor self.scale_factor
} }
pub fn paint_stacking_context<F>(
&mut self,
clip_bounds: Option<RectF>,
z_index: Option<usize>,
f: F,
) where
F: FnOnce(&mut Self),
{
self.push_stacking_context(clip_bounds, z_index);
f(self);
self.pop_stacking_context();
}
pub fn push_stacking_context(&mut self, clip_bounds: Option<RectF>, z_index: Option<usize>) { pub fn push_stacking_context(&mut self, clip_bounds: Option<RectF>, z_index: Option<usize>) {
let z_index = z_index.unwrap_or_else(|| self.active_stacking_context().z_index + 1); let z_index = z_index.unwrap_or_else(|| self.active_stacking_context().z_index + 1);
self.active_stacking_context_stack self.active_stacking_context_stack
@ -249,6 +262,15 @@ impl SceneBuilder {
assert!(!self.active_stacking_context_stack.is_empty()); assert!(!self.active_stacking_context_stack.is_empty());
} }
pub fn paint_layer<F>(&mut self, clip_bounds: Option<RectF>, f: F)
where
F: FnOnce(&mut Self),
{
self.push_layer(clip_bounds);
f(self);
self.pop_layer();
}
pub fn push_layer(&mut self, clip_bounds: Option<RectF>) { pub fn push_layer(&mut self, clip_bounds: Option<RectF>) {
self.active_stacking_context().push_layer(clip_bounds); self.active_stacking_context().push_layer(clip_bounds);
} }

View File

@ -1,4 +1,10 @@
use std::{any::TypeId, fmt::Debug, mem::Discriminant, rc::Rc}; use std::{
any::{Any, TypeId},
fmt::Debug,
mem::Discriminant,
ops::{Deref, DerefMut},
rc::Rc,
};
use collections::HashMap; use collections::HashMap;
@ -63,7 +69,7 @@ impl MouseRegion {
pub fn on_down<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_down<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseDown, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseDown, &mut V, &mut EventContext<V>) + 'static,
{ {
self.handlers = self.handlers.on_down(button, handler); self.handlers = self.handlers.on_down(button, handler);
self self
@ -72,7 +78,7 @@ impl MouseRegion {
pub fn on_up<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_up<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseUp, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseUp, &mut V, &mut EventContext<V>) + 'static,
{ {
self.handlers = self.handlers.on_up(button, handler); self.handlers = self.handlers.on_up(button, handler);
self self
@ -81,7 +87,7 @@ impl MouseRegion {
pub fn on_click<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_click<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseClick, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
{ {
self.handlers = self.handlers.on_click(button, handler); self.handlers = self.handlers.on_click(button, handler);
self self
@ -90,7 +96,7 @@ impl MouseRegion {
pub fn on_down_out<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_down_out<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseDownOut, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseDownOut, &mut V, &mut EventContext<V>) + 'static,
{ {
self.handlers = self.handlers.on_down_out(button, handler); self.handlers = self.handlers.on_down_out(button, handler);
self self
@ -99,7 +105,7 @@ impl MouseRegion {
pub fn on_up_out<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_up_out<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseUpOut, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseUpOut, &mut V, &mut EventContext<V>) + 'static,
{ {
self.handlers = self.handlers.on_up_out(button, handler); self.handlers = self.handlers.on_up_out(button, handler);
self self
@ -108,7 +114,7 @@ impl MouseRegion {
pub fn on_drag<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_drag<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseDrag, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseDrag, &mut V, &mut EventContext<V>) + 'static,
{ {
self.handlers = self.handlers.on_drag(button, handler); self.handlers = self.handlers.on_drag(button, handler);
self self
@ -117,7 +123,7 @@ impl MouseRegion {
pub fn on_hover<V, F>(mut self, handler: F) -> Self pub fn on_hover<V, F>(mut self, handler: F) -> Self
where where
V: View, V: View,
F: Fn(&mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseHover, &mut V, &mut EventContext<V>) + 'static,
{ {
self.handlers = self.handlers.on_hover(handler); self.handlers = self.handlers.on_hover(handler);
self self
@ -126,7 +132,7 @@ impl MouseRegion {
pub fn on_move<V, F>(mut self, handler: F) -> Self pub fn on_move<V, F>(mut self, handler: F) -> Self
where where
V: View, V: View,
F: Fn(&mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseMove, &mut V, &mut EventContext<V>) + 'static,
{ {
self.handlers = self.handlers.on_move(handler); self.handlers = self.handlers.on_move(handler);
self self
@ -135,7 +141,7 @@ impl MouseRegion {
pub fn on_move_out<V, F>(mut self, handler: F) -> Self pub fn on_move_out<V, F>(mut self, handler: F) -> Self
where where
V: View, V: View,
F: Fn(&mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseMoveOut, &mut V, &mut EventContext<V>) + 'static,
{ {
self.handlers = self.handlers.on_move_out(handler); self.handlers = self.handlers.on_move_out(handler);
self self
@ -144,7 +150,7 @@ impl MouseRegion {
pub fn on_scroll<V, F>(mut self, handler: F) -> Self pub fn on_scroll<V, F>(mut self, handler: F) -> Self
where where
V: View, V: View,
F: Fn(&mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseScrollWheel, &mut V, &mut EventContext<V>) + 'static,
{ {
self.handlers = self.handlers.on_scroll(handler); self.handlers = self.handlers.on_scroll(handler);
self self
@ -196,7 +202,39 @@ impl MouseRegionId {
} }
} }
pub type HandlerCallback = Rc<dyn Fn(MouseEvent, &mut WindowContext)>; pub struct EventContext<'a, 'b, 'c, 'd, V: View> {
view_context: &'d mut ViewContext<'a, 'b, 'c, V>,
handled: bool,
}
impl<'a, 'b, 'c, 'd, V: View> EventContext<'a, 'b, 'c, 'd, V> {
fn new(view_context: &'d mut ViewContext<'a, 'b, 'c, V>) -> Self {
EventContext {
view_context,
handled: true,
}
}
pub fn propagate_event(&mut self) {
self.handled = false;
}
}
impl<'a, 'b, 'c, 'd, V: View> Deref for EventContext<'a, 'b, 'c, 'd, V> {
type Target = ViewContext<'a, 'b, 'c, V>;
fn deref(&self) -> &Self::Target {
&self.view_context
}
}
impl<V: View> DerefMut for EventContext<'_, '_, '_, '_, V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.view_context
}
}
pub type HandlerCallback = Rc<dyn Fn(MouseEvent, &mut dyn Any, &mut WindowContext, usize) -> bool>;
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub struct HandlerKey { pub struct HandlerKey {
@ -221,41 +259,41 @@ impl HandlerSet {
set.insert( set.insert(
HandlerKey::new(MouseEvent::move_disc(), None), HandlerKey::new(MouseEvent::move_disc(), None),
SmallVec::from_buf([Rc::new(|_, _| {})]), SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
); );
set.insert( set.insert(
HandlerKey::new(MouseEvent::hover_disc(), None), HandlerKey::new(MouseEvent::hover_disc(), None),
SmallVec::from_buf([Rc::new(|_, _| {})]), SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
); );
for button in MouseButton::all() { for button in MouseButton::all() {
set.insert( set.insert(
HandlerKey::new(MouseEvent::drag_disc(), Some(button)), HandlerKey::new(MouseEvent::drag_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]), SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
); );
set.insert( set.insert(
HandlerKey::new(MouseEvent::down_disc(), Some(button)), HandlerKey::new(MouseEvent::down_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]), SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
); );
set.insert( set.insert(
HandlerKey::new(MouseEvent::up_disc(), Some(button)), HandlerKey::new(MouseEvent::up_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]), SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
); );
set.insert( set.insert(
HandlerKey::new(MouseEvent::click_disc(), Some(button)), HandlerKey::new(MouseEvent::click_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]), SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
); );
set.insert( set.insert(
HandlerKey::new(MouseEvent::down_out_disc(), Some(button)), HandlerKey::new(MouseEvent::down_out_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]), SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
); );
set.insert( set.insert(
HandlerKey::new(MouseEvent::up_out_disc(), Some(button)), HandlerKey::new(MouseEvent::up_out_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]), SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
); );
} }
set.insert( set.insert(
HandlerKey::new(MouseEvent::scroll_wheel_disc(), None), HandlerKey::new(MouseEvent::scroll_wheel_disc(), None),
SmallVec::from_buf([Rc::new(|_, _| {})]), SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
); );
HandlerSet { set } HandlerSet { set }
@ -296,12 +334,16 @@ impl HandlerSet {
pub fn on_move<V, F>(mut self, handler: F) -> Self pub fn on_move<V, F>(mut self, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseMove, &mut V, &mut ViewContext<Self>) + 'static, F: Fn(MouseMove, &mut V, &mut EventContext<V>) + 'static,
{ {
self.insert(MouseEvent::move_disc(), None, self.insert(MouseEvent::move_disc(), None,
Rc::new(move |region_event, cx| { Rc::new(move |region_event, view, cx, view_id| {
if let MouseEvent::Move(e) = region_event { if let MouseEvent::Move(e) = region_event {
handler(e, cx); let view = view.downcast_mut().unwrap();
let mut cx = ViewContext::mutable(cx, view_id);
let mut cx = EventContext::new(&mut cx);
handler(e, view, &mut cx);
cx.handled
} else { } else {
panic!( panic!(
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Move, found {:?}", "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Move, found {:?}",
@ -314,12 +356,16 @@ impl HandlerSet {
pub fn on_move_out<V, F>(mut self, handler: F) -> Self pub fn on_move_out<V, F>(mut self, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseMoveOut, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseMoveOut, &mut V, &mut EventContext<V>) + 'static,
{ {
self.insert(MouseEvent::move_out_disc(), None, self.insert(MouseEvent::move_out_disc(), None,
Rc::new(move |region_event, cx| { Rc::new(move |region_event, view, cx, view_id| {
if let MouseEvent::MoveOut(e) = region_event { if let MouseEvent::MoveOut(e) = region_event {
handler(e, cx); let view = view.downcast_mut().unwrap();
let mut cx = ViewContext::<V>::mutable(cx, view_id);
let mut cx = EventContext::new(&mut cx);
handler(e, view, &mut cx);
cx.handled
} else { } else {
panic!( panic!(
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::MoveOut, found {:?}", "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::MoveOut, found {:?}",
@ -332,12 +378,16 @@ impl HandlerSet {
pub fn on_down<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_down<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseDown, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseDown, &mut V, &mut EventContext<V>) + 'static,
{ {
self.insert(MouseEvent::down_disc(), Some(button), self.insert(MouseEvent::down_disc(), Some(button),
Rc::new(move |region_event, cx| { Rc::new(move |region_event, view, cx, view_id| {
if let MouseEvent::Down(e) = region_event { if let MouseEvent::Down(e) = region_event {
handler(e, cx); let view = view.downcast_mut().unwrap();
let mut cx = ViewContext::mutable(cx, view_id);
let mut cx = EventContext::new(&mut cx);
handler(e, view, &mut cx);
cx.handled
} else { } else {
panic!( panic!(
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Down, found {:?}", "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Down, found {:?}",
@ -350,12 +400,16 @@ impl HandlerSet {
pub fn on_up<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_up<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseUp, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseUp, &mut V, &mut EventContext<V>) + 'static,
{ {
self.insert(MouseEvent::up_disc(), Some(button), self.insert(MouseEvent::up_disc(), Some(button),
Rc::new(move |region_event, cx| { Rc::new(move |region_event, view, cx, view_id| {
if let MouseEvent::Up(e) = region_event { if let MouseEvent::Up(e) = region_event {
handler(e, cx); let view = view.downcast_mut().unwrap();
let mut cx = ViewContext::mutable(cx, view_id);
let mut cx = EventContext::new(&mut cx);
handler(e, view, &mut cx);
cx.handled
} else { } else {
panic!( panic!(
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Up, found {:?}", "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Up, found {:?}",
@ -368,12 +422,16 @@ impl HandlerSet {
pub fn on_click<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_click<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseClick, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
{ {
self.insert(MouseEvent::click_disc(), Some(button), self.insert(MouseEvent::click_disc(), Some(button),
Rc::new(move |region_event, cx| { Rc::new(move |region_event, view, cx, view_id| {
if let MouseEvent::Click(e) = region_event { if let MouseEvent::Click(e) = region_event {
handler(e, cx); let view = view.downcast_mut().unwrap();
let mut cx = ViewContext::mutable(cx, view_id);
let mut cx = EventContext::new(&mut cx);
handler(e, view, &mut cx);
cx.handled
} else { } else {
panic!( panic!(
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Click, found {:?}", "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Click, found {:?}",
@ -386,12 +444,16 @@ impl HandlerSet {
pub fn on_down_out<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_down_out<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseDownOut, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseDownOut, &mut V, &mut EventContext<V>) + 'static,
{ {
self.insert(MouseEvent::down_out_disc(), Some(button), self.insert(MouseEvent::down_out_disc(), Some(button),
Rc::new(move |region_event, cx| { Rc::new(move |region_event, view, cx, view_id| {
if let MouseEvent::DownOut(e) = region_event { if let MouseEvent::DownOut(e) = region_event {
handler(e, cx); let view = view.downcast_mut().unwrap();
let mut cx = ViewContext::mutable(cx, view_id);
let mut cx = EventContext::new(&mut cx);
handler(e, view, &mut cx);
cx.handled
} else { } else {
panic!( panic!(
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::DownOut, found {:?}", "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::DownOut, found {:?}",
@ -404,12 +466,16 @@ impl HandlerSet {
pub fn on_up_out<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_up_out<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseUpOut, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseUpOut, &mut V, &mut EventContext<V>) + 'static,
{ {
self.insert(MouseEvent::up_out_disc(), Some(button), self.insert(MouseEvent::up_out_disc(), Some(button),
Rc::new(move |region_event, cx| { Rc::new(move |region_event, view, cx, view_id| {
if let MouseEvent::UpOut(e) = region_event { if let MouseEvent::UpOut(e) = region_event {
handler(e, cx); let view = view.downcast_mut().unwrap();
let mut cx = ViewContext::mutable(cx, view_id);
let mut cx = EventContext::new(&mut cx);
handler(e, view, &mut cx);
cx.handled
} else { } else {
panic!( panic!(
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::UpOut, found {:?}", "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::UpOut, found {:?}",
@ -422,12 +488,16 @@ impl HandlerSet {
pub fn on_drag<V, F>(mut self, button: MouseButton, handler: F) -> Self pub fn on_drag<V, F>(mut self, button: MouseButton, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseDrag, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseDrag, &mut V, &mut EventContext<V>) + 'static,
{ {
self.insert(MouseEvent::drag_disc(), Some(button), self.insert(MouseEvent::drag_disc(), Some(button),
Rc::new(move |region_event, cx| { Rc::new(move |region_event, view, cx, view_id| {
if let MouseEvent::Drag(e) = region_event { if let MouseEvent::Drag(e) = region_event {
handler(e, cx); let view = view.downcast_mut().unwrap();
let mut cx = ViewContext::mutable(cx, view_id);
let mut cx = EventContext::new(&mut cx);
handler(e, view, &mut cx);
cx.handled
} else { } else {
panic!( panic!(
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Drag, found {:?}", "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Drag, found {:?}",
@ -440,12 +510,16 @@ impl HandlerSet {
pub fn on_hover<V, F>(mut self, handler: F) -> Self pub fn on_hover<V, F>(mut self, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseHover, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseHover, &mut V, &mut EventContext<V>) + 'static,
{ {
self.insert(MouseEvent::hover_disc(), None, self.insert(MouseEvent::hover_disc(), None,
Rc::new(move |region_event, cx| { Rc::new(move |region_event, view, cx, view_id| {
if let MouseEvent::Hover(e) = region_event { if let MouseEvent::Hover(e) = region_event {
handler(e, cx); let view = view.downcast_mut().unwrap();
let mut cx = ViewContext::mutable(cx, view_id);
let mut cx = EventContext::new(&mut cx);
handler(e, view, &mut cx);
cx.handled
} else { } else {
panic!( panic!(
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Hover, found {:?}", "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Hover, found {:?}",
@ -458,12 +532,16 @@ impl HandlerSet {
pub fn on_scroll<V, F>(mut self, handler: F) -> Self pub fn on_scroll<V, F>(mut self, handler: F) -> Self
where where
V: View, V: View,
F: Fn(MouseScrollWheel, &mut V, &mut ViewContext<V>) + 'static, F: Fn(MouseScrollWheel, &mut V, &mut EventContext<V>) + 'static,
{ {
self.insert(MouseEvent::scroll_wheel_disc(), None, self.insert(MouseEvent::scroll_wheel_disc(), None,
Rc::new(move |region_event, cx| { Rc::new(move |region_event, view, cx, view_id| {
if let MouseEvent::ScrollWheel(e) = region_event { if let MouseEvent::ScrollWheel(e) = region_event {
handler(e, cx); let view = view.downcast_mut().unwrap();
let mut cx = ViewContext::mutable(cx, view_id);
let mut cx = EventContext::new(&mut cx);
handler(e, view, &mut cx);
cx.handled
} else { } else {
panic!( panic!(
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::ScrollWheel, found {:?}", "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::ScrollWheel, found {:?}",

View File

@ -273,7 +273,7 @@ impl Line {
pub fn paint( pub fn paint(
&self, &self,
scene: &SceneBuilder, scene: &mut SceneBuilder,
origin: Vector2F, origin: Vector2F,
visible_bounds: RectF, visible_bounds: RectF,
line_height: f32, line_height: f32,
@ -334,7 +334,7 @@ impl Line {
} }
if let Some((underline_origin, underline_style)) = finished_underline { if let Some((underline_origin, underline_style)) = finished_underline {
cx.scene.push_underline(scene::Underline { scene.push_underline(scene::Underline {
origin: underline_origin, origin: underline_origin,
width: glyph_origin.x() - underline_origin.x(), width: glyph_origin.x() - underline_origin.x(),
thickness: underline_style.thickness.into(), thickness: underline_style.thickness.into(),
@ -344,14 +344,14 @@ impl Line {
} }
if glyph.is_emoji { if glyph.is_emoji {
cx.scene.push_image_glyph(scene::ImageGlyph { scene.push_image_glyph(scene::ImageGlyph {
font_id: run.font_id, font_id: run.font_id,
font_size: self.layout.font_size, font_size: self.layout.font_size,
id: glyph.id, id: glyph.id,
origin: glyph_origin, origin: glyph_origin,
}); });
} else { } else {
cx.scene.push_glyph(scene::Glyph { scene.push_glyph(scene::Glyph {
font_id: run.font_id, font_id: run.font_id,
font_size: self.layout.font_size, font_size: self.layout.font_size,
id: glyph.id, id: glyph.id,
@ -364,7 +364,7 @@ impl Line {
if let Some((underline_start, underline_style)) = underline.take() { if let Some((underline_start, underline_style)) = underline.take() {
let line_end_x = origin.x() + self.layout.width; let line_end_x = origin.x() + self.layout.width;
cx.scene.push_underline(scene::Underline { scene.push_underline(scene::Underline {
origin: underline_start, origin: underline_start,
width: line_end_x - underline_start.x(), width: line_end_x - underline_start.x(),
color: underline_style.color.unwrap(), color: underline_style.color.unwrap(),
@ -376,7 +376,7 @@ impl Line {
pub fn paint_wrapped( pub fn paint_wrapped(
&self, &self,
scene: &SceneBuilder, scene: &mut SceneBuilder,
origin: Vector2F, origin: Vector2F,
visible_bounds: RectF, visible_bounds: RectF,
line_height: f32, line_height: f32,

View File

@ -106,11 +106,7 @@ impl View for Select {
Default::default() Default::default()
}; };
let mut result = Flex::column().with_child( let mut result = Flex::column().with_child(
MouseEventHandler::<Header>::new( MouseEventHandler::<Header, _>::new(self.handle.id(), cx, |mouse_state, cx| {
self.handle.id(),
self,
cx,
|mouse_state, this, cx| {
Container::new((self.render_item)( Container::new((self.render_item)(
self.selected_item_ix, self.selected_item_ix,
ItemType::Header, ItemType::Header,
@ -119,9 +115,8 @@ impl View for Select {
)) ))
.with_style(style.header) .with_style(style.header)
.boxed() .boxed()
}, })
) .on_click(MouseButton::Left, move |_, _, cx| {
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(ToggleSelect) cx.dispatch_action(ToggleSelect)
}) })
.boxed(), .boxed(),
@ -139,11 +134,10 @@ impl View for Select {
let selected_item_ix = this.selected_item_ix; let selected_item_ix = this.selected_item_ix;
range.end = range.end.min(this.item_count); range.end = range.end.min(this.item_count);
items.extend(range.map(|ix| { items.extend(range.map(|ix| {
MouseEventHandler::<Item>::new( MouseEventHandler::<Item, _>::new(
ix, ix,
self,
cx, cx,
|mouse_state, this, cx| { |mouse_state, cx| {
(this.render_item)( (this.render_item)(
ix, ix,
if ix == selected_item_ix { if ix == selected_item_ix {
@ -156,7 +150,7 @@ impl View for Select {
) )
}, },
) )
.on_click(MouseButton::Left, move |_, cx| { .on_click(MouseButton::Left, move |_, _, cx| {
cx.dispatch_action(SelectItem(ix)) cx.dispatch_action(SelectItem(ix))
}) })
.boxed() .boxed()

View File

@ -2,7 +2,7 @@ use editor::Editor;
use gpui::{ use gpui::{
elements::*, elements::*,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
Entity, RenderContext, Subscription, View, ViewContext, ViewHandle, Entity, Subscription, View, ViewContext, ViewHandle,
}; };
use settings::Settings; use settings::Settings;
use std::sync::Arc; use std::sync::Arc;
@ -50,7 +50,7 @@ impl View for ActiveBufferLanguage {
"ActiveBufferLanguage" "ActiveBufferLanguage"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
if let Some(active_language) = self.active_language.as_ref() { if let Some(active_language) = self.active_language.as_ref() {
let active_language_text = if let Some(active_language_text) = active_language { let active_language_text = if let Some(active_language_text) = active_language {
active_language_text.to_string() active_language_text.to_string()

View File

@ -4,8 +4,8 @@ pub use active_buffer_language::ActiveBufferLanguage;
use editor::Editor; use editor::Editor;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, View,
RenderContext, View, ViewContext, ViewHandle, ViewContext, ViewHandle,
}; };
use language::{Buffer, LanguageRegistry}; use language::{Buffer, LanguageRegistry};
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
@ -120,7 +120,7 @@ impl View for LanguageSelector {
"LanguageSelector" "LanguageSelector"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
ChildView::new(&self.picker, cx).boxed() ChildView::new(&self.picker, cx).boxed()
} }

View File

@ -5,7 +5,7 @@ use editor::{
use fuzzy::StringMatch; use fuzzy::StringMatch;
use gpui::{ use gpui::{
actions, elements::*, geometry::vector::Vector2F, AnyViewHandle, AppContext, Entity, actions, elements::*, geometry::vector::Vector2F, AnyViewHandle, AppContext, Entity,
MouseState, RenderContext, Task, View, ViewContext, ViewHandle, MouseState, Task, View, ViewContext, ViewHandle,
}; };
use language::Outline; use language::Outline;
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
@ -48,7 +48,7 @@ impl View for OutlineView {
"OutlineView" "OutlineView"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
ChildView::new(&self.picker, cx).boxed() ChildView::new(&self.picker, cx).boxed()
} }

View File

@ -4,8 +4,8 @@ use gpui::{
geometry::vector::{vec2f, Vector2F}, geometry::vector::{vec2f, Vector2F},
keymap_matcher::KeymapContext, keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
AnyViewHandle, AppContext, Axis, Entity, MouseState, RenderContext, Task, View, ViewContext, AnyViewHandle, AppContext, Axis, Entity, MouseState, Task, View, ViewContext, ViewHandle,
ViewHandle, WeakViewHandle, WeakViewHandle,
}; };
use menu::{Cancel, Confirm, SelectFirst, SelectIndex, SelectLast, SelectNext, SelectPrev}; use menu::{Cancel, Confirm, SelectFirst, SelectIndex, SelectLast, SelectNext, SelectPrev};
use parking_lot::Mutex; use parking_lot::Mutex;
@ -48,7 +48,7 @@ impl<D: PickerDelegate> View for Picker<D> {
"Picker" "Picker"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> gpui::ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> gpui::ElementBox {
let theme = (self.theme.lock())(&cx.global::<settings::Settings>().theme); let theme = (self.theme.lock())(&cx.global::<settings::Settings>().theme);
let query = self.query(cx); let query = self.query(cx);
let delegate = self.delegate.clone(); let delegate = self.delegate.clone();

View File

@ -13,8 +13,8 @@ use gpui::{
impl_internal_actions, impl_internal_actions,
keymap_matcher::KeymapContext, keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton, PromptLevel}, platform::{CursorStyle, MouseButton, PromptLevel},
AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle, RenderContext, Task, View, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle, Task, View, ViewContext,
ViewContext, ViewHandle, ViewHandle,
}; };
use menu::{Confirm, SelectNext, SelectPrev}; use menu::{Confirm, SelectNext, SelectPrev};
use project::{Entry, EntryKind, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId}; use project::{Entry, EntryKind, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
@ -1015,8 +1015,8 @@ impl ProjectPanel {
fn for_each_visible_entry( fn for_each_visible_entry(
&self, &self,
range: Range<usize>, range: Range<usize>,
cx: &mut RenderContext<ProjectPanel>, cx: &mut ViewContext<ProjectPanel>,
mut callback: impl FnMut(ProjectEntryId, EntryDetails, &mut RenderContext<ProjectPanel>), mut callback: impl FnMut(ProjectEntryId, EntryDetails, &mut ViewContext<ProjectPanel>),
) { ) {
let mut ix = 0; let mut ix = 0;
for (worktree_id, visible_worktree_entries) in &self.visible_entries { for (worktree_id, visible_worktree_entries) in &self.visible_entries {
@ -1097,7 +1097,7 @@ impl ProjectPanel {
padding: f32, padding: f32,
row_container_style: ContainerStyle, row_container_style: ContainerStyle,
style: &ProjectPanelEntry, style: &ProjectPanelEntry,
cx: &mut RenderContext<V>, cx: &mut ViewContext<V>,
) -> ElementBox { ) -> ElementBox {
let kind = details.kind; let kind = details.kind;
let show_editor = details.is_editing && !details.is_processing; let show_editor = details.is_editing && !details.is_processing;
@ -1154,7 +1154,7 @@ impl ProjectPanel {
editor: &ViewHandle<Editor>, editor: &ViewHandle<Editor>,
dragged_entry_destination: &mut Option<Arc<Path>>, dragged_entry_destination: &mut Option<Arc<Path>>,
theme: &theme::ProjectPanel, theme: &theme::ProjectPanel,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let this = cx.handle(); let this = cx.handle();
let kind = details.kind; let kind = details.kind;
@ -1251,7 +1251,7 @@ impl ProjectPanel {
.as_draggable(entry_id, { .as_draggable(entry_id, {
let row_container_style = theme.dragged_entry.container; let row_container_style = theme.dragged_entry.container;
move |_, cx: &mut RenderContext<Workspace>| { move |_, cx: &mut ViewContext<Workspace>| {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
Self::render_entry_visual_element( Self::render_entry_visual_element(
&details, &details,
@ -1273,7 +1273,7 @@ impl View for ProjectPanel {
"ProjectPanel" "ProjectPanel"
} }
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox { fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> gpui::ElementBox {
enum ProjectPanel {} enum ProjectPanel {}
let theme = &cx.global::<Settings>().theme.project_panel; let theme = &cx.global::<Settings>().theme.project_panel;
let mut container_style = theme.container; let mut container_style = theme.container;

View File

@ -4,8 +4,8 @@ use editor::{
}; };
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, Task, View,
RenderContext, Task, View, ViewContext, ViewHandle, ViewContext, ViewHandle,
}; };
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
@ -48,7 +48,7 @@ impl View for ProjectSymbolsView {
"ProjectSymbolsView" "ProjectSymbolsView"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
ChildView::new(&self.picker, cx).boxed() ChildView::new(&self.picker, cx).boxed()
} }

View File

@ -4,8 +4,7 @@ use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
actions, actions,
elements::{ChildView, Flex, ParentElement}, elements::{ChildView, Flex, ParentElement},
AnyViewHandle, AppContext, Element, ElementBox, Entity, RenderContext, Task, View, ViewContext, AnyViewHandle, AppContext, Element, ElementBox, Entity, Task, View, ViewContext, ViewHandle,
ViewHandle,
}; };
use highlighted_workspace_location::HighlightedWorkspaceLocation; use highlighted_workspace_location::HighlightedWorkspaceLocation;
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
@ -102,7 +101,7 @@ impl View for RecentProjectsView {
"RecentProjectsView" "RecentProjectsView"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
ChildView::new(&self.picker, cx).boxed() ChildView::new(&self.picker, cx).boxed()
} }

View File

@ -9,8 +9,7 @@ use gpui::{
elements::*, elements::*,
impl_actions, impl_actions,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
Action, AnyViewHandle, AppContext, Entity, RenderContext, Subscription, Task, View, Action, AnyViewHandle, AppContext, Entity, Subscription, Task, View, ViewContext, ViewHandle,
ViewContext, ViewHandle,
}; };
use project::search::SearchQuery; use project::search::SearchQuery;
use serde::Deserialize; use serde::Deserialize;
@ -92,7 +91,7 @@ impl View for BufferSearchBar {
} }
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
let editor_container = if self.query_contains_error { let editor_container = if self.query_contains_error {
theme.search.invalid_editor theme.search.invalid_editor
@ -324,7 +323,7 @@ impl BufferSearchBar {
option_supported: bool, option_supported: bool,
icon: &'static str, icon: &'static str,
option: SearchOption, option: SearchOption,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> Option<ElementBox> { ) -> Option<ElementBox> {
if !option_supported { if !option_supported {
return None; return None;
@ -364,7 +363,7 @@ impl BufferSearchBar {
&self, &self,
icon: &'static str, icon: &'static str,
direction: Direction, direction: Direction,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let action: Box<dyn Action>; let action: Box<dyn Action>;
let tooltip; let tooltip;
@ -408,11 +407,7 @@ impl BufferSearchBar {
.boxed() .boxed()
} }
fn render_close_button( fn render_close_button(&self, theme: &theme::Search, cx: &mut ViewContext<Self>) -> ElementBox {
&self,
theme: &theme::Search,
cx: &mut RenderContext<Self>,
) -> ElementBox {
let action = Box::new(Dismiss); let action = Box::new(Dismiss);
let tooltip = "Dismiss Buffer Search"; let tooltip = "Dismiss Buffer Search";
let tooltip_style = cx.global::<Settings>().theme.tooltip.clone(); let tooltip_style = cx.global::<Settings>().theme.tooltip.clone();

View File

@ -12,9 +12,8 @@ use gpui::{
actions, actions,
elements::*, elements::*,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
Action, AnyViewHandle, AppContext, Entity, ModelContext, ModelHandle, RenderContext, Action, AnyViewHandle, AppContext, ElementBox, Entity, ModelContext, ModelHandle, Subscription,
Subscription, Task, View, ViewContext, ElementBox, ViewHandle, WeakModelHandle, Task, View, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle,
WeakViewHandle,
}; };
use menu::Confirm; use menu::Confirm;
use project::{search::SearchQuery, Project}; use project::{search::SearchQuery, Project};
@ -178,7 +177,7 @@ impl View for ProjectSearchView {
"ProjectSearchView" "ProjectSearchView"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let model = &self.model.read(cx); let model = &self.model.read(cx);
if model.match_ranges.is_empty() { if model.match_ranges.is_empty() {
enum Status {} enum Status {}
@ -747,7 +746,7 @@ impl ProjectSearchBar {
&self, &self,
icon: &'static str, icon: &'static str,
direction: Direction, direction: Direction,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let action: Box<dyn Action>; let action: Box<dyn Action>;
let tooltip; let tooltip;
@ -795,7 +794,7 @@ impl ProjectSearchBar {
&self, &self,
icon: &'static str, icon: &'static str,
option: SearchOption, option: SearchOption,
cx: &mut RenderContext<Self>, cx: &mut ViewContext<Self>,
) -> ElementBox { ) -> ElementBox {
let tooltip_style = cx.global::<Settings>().theme.tooltip.clone(); let tooltip_style = cx.global::<Settings>().theme.tooltip.clone();
let is_active = self.is_option_enabled(option, cx); let is_active = self.is_option_enabled(option, cx);
@ -848,7 +847,7 @@ impl View for ProjectSearchBar {
"ProjectSearchBar" "ProjectSearchBar"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
if let Some(search) = self.active_project_search.as_ref() { if let Some(search) = self.active_project_search.as_ref() {
let search = search.read(cx); let search = search.read(cx);
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();

View File

@ -3,8 +3,8 @@ use gpui::{
elements::*, elements::*,
impl_internal_actions, impl_internal_actions,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
AppContext, Element, ElementBox, Entity, RenderContext, View, ViewContext, ViewHandle, AppContext, Element, ElementBox, Entity, View, ViewContext, ViewHandle, WeakModelHandle,
WeakModelHandle, WeakViewHandle, WeakViewHandle,
}; };
use settings::Settings; use settings::Settings;
use std::any::TypeId; use std::any::TypeId;
@ -42,14 +42,14 @@ impl View for TerminalButton {
"TerminalButton" "TerminalButton"
} }
fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> ElementBox {
let workspace = self.workspace.upgrade(cx); let workspace = self.workspace.upgrade(cx);
let project = match workspace { let project = match workspace {
Some(workspace) => workspace.read(cx).project().read(cx), Some(workspace) => workspace.read(cx).project().read(cx),
None => return Empty::new().boxed(), None => return Empty::new().boxed(),
}; };
let focused_view = cx.focused_view_id(cx.window_id()); let focused_view = cx.focused_view_id();
let active = focused_view let active = focused_view
.map(|view_id| { .map(|view_id| {
cx.view_type_id(cx.window_id(), view_id) == Some(TypeId::of::<TerminalView>()) cx.view_type_id(cx.window_id(), view_id) == Some(TypeId::of::<TerminalView>())

View File

@ -10,8 +10,8 @@ use gpui::{
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
serde_json::json, serde_json::json,
text_layout::{Line, RunStyle}, text_layout::{Line, RunStyle},
Element, ElementBox, EventContext, FontCache, ModelContext, MouseRegion, PaintContext, Quad, Element, ElementBox, EventContext, FontCache, ModelContext, MouseRegion, Quad, SceneBuilder,
SizeConstraint, TextLayoutCache, WeakModelHandle, WeakViewHandle, SizeConstraint, TextLayoutCache, ViewContext, WeakModelHandle, WeakViewHandle,
}; };
use itertools::Itertools; use itertools::Itertools;
use language::CursorShape; use language::CursorShape;
@ -45,7 +45,7 @@ pub struct LayoutState {
size: TerminalSize, size: TerminalSize,
mode: TermMode, mode: TermMode,
display_offset: usize, display_offset: usize,
hyperlink_tooltip: Option<ElementBox>, hyperlink_tooltip: Option<ElementBox<TerminalView>>,
} }
///Helper struct for converting data between alacritty's cursor points, and displayed cursor points ///Helper struct for converting data between alacritty's cursor points, and displayed cursor points
@ -84,10 +84,12 @@ impl LayoutCell {
fn paint( fn paint(
&self, &self,
scene: &mut SceneBuilder,
origin: Vector2F, origin: Vector2F,
layout: &LayoutState, layout: &LayoutState,
visible_bounds: RectF, visible_bounds: RectF,
cx: &mut PaintContext, view: &mut TerminalView,
cx: &mut ViewContext<TerminalView>,
) { ) {
let pos = { let pos = {
let point = self.point; let point = self.point;
@ -98,7 +100,7 @@ impl LayoutCell {
}; };
self.text self.text
.paint(pos, visible_bounds, layout.size.line_height, cx); .paint(pos, visible_bounds, layout.size.line_height, view, cx);
} }
} }
@ -139,7 +141,7 @@ impl LayoutRect {
layout.size.line_height, layout.size.line_height,
); );
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: RectF::new(position, size), bounds: RectF::new(position, size),
background: Some(self.color), background: Some(self.color),
border: Default::default(), border: Default::default(),
@ -380,7 +382,7 @@ impl TerminalElement {
view_id: usize, view_id: usize,
visible_bounds: RectF, visible_bounds: RectF,
mode: TermMode, mode: TermMode,
cx: &mut PaintContext, cx: &mut ViewContext<TerminalView>,
) { ) {
let connection = self.terminal; let connection = self.terminal;
@ -501,7 +503,7 @@ impl TerminalElement {
) )
} }
cx.scene.push_mouse_region(region); scene.push_mouse_region(region);
} }
///Configures a text style from the current settings. ///Configures a text style from the current settings.
@ -553,7 +555,8 @@ impl Element for TerminalElement {
fn layout( fn layout(
&mut self, &mut self,
constraint: gpui::SizeConstraint, constraint: gpui::SizeConstraint,
cx: &mut gpui::LayoutContext, view: &mut TerminalView,
cx: &mut ViewContext<TerminalView>,
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
let settings = cx.global::<Settings>(); let settings = cx.global::<Settings>();
let font_cache = cx.font_cache(); let font_cache = cx.font_cache();
@ -717,23 +720,24 @@ impl Element for TerminalElement {
fn paint( fn paint(
&mut self, &mut self,
bounds: gpui::geometry::rect::RectF, scene: &mut SceneBuilder,
visible_bounds: gpui::geometry::rect::RectF, bounds: RectF,
visible_bounds: RectF,
layout: &mut Self::LayoutState, layout: &mut Self::LayoutState,
cx: &mut gpui::PaintContext, cx: &mut ViewContext<TerminalView>,
) -> Self::PaintState { ) -> Self::PaintState {
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
//Setup element stuff //Setup element stuff
let clip_bounds = Some(visible_bounds); let clip_bounds = Some(visible_bounds);
cx.paint_layer(clip_bounds, |cx| { scene.paint_layer(clip_bounds, |scene| {
let origin = bounds.origin() + vec2f(layout.size.cell_width, 0.); let origin = bounds.origin() + vec2f(layout.size.cell_width, 0.);
// Elements are ephemeral, only at paint time do we know what could be clicked by a mouse // Elements are ephemeral, only at paint time do we know what could be clicked by a mouse
self.attach_mouse_handlers(origin, self.view.id(), visible_bounds, layout.mode, cx); self.attach_mouse_handlers(origin, self.view.id(), visible_bounds, layout.mode, cx);
cx.scene.push_cursor_region(gpui::CursorRegion { scene.push_cursor_region(gpui::CursorRegion {
bounds, bounds,
style: if layout.hyperlink_tooltip.is_some() { style: if layout.hyperlink_tooltip.is_some() {
CursorStyle::PointingHand CursorStyle::PointingHand
@ -742,9 +746,9 @@ impl Element for TerminalElement {
}, },
}); });
cx.paint_layer(clip_bounds, |cx| { scene.paint_layer(clip_bounds, |scene| {
//Start with a background color //Start with a background color
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: RectF::new(bounds.origin(), bounds.size()), bounds: RectF::new(bounds.origin(), bounds.size()),
background: Some(layout.background_color), background: Some(layout.background_color),
border: Default::default(), border: Default::default(),
@ -757,7 +761,7 @@ impl Element for TerminalElement {
}); });
//Draw Highlighted Backgrounds //Draw Highlighted Backgrounds
cx.paint_layer(clip_bounds, |cx| { scene.paint_layer(clip_bounds, |scene| {
for (relative_highlighted_range, color) in layout.relative_highlighted_ranges.iter() for (relative_highlighted_range, color) in layout.relative_highlighted_ranges.iter()
{ {
if let Some((start_y, highlighted_range_lines)) = if let Some((start_y, highlighted_range_lines)) =
@ -771,29 +775,29 @@ impl Element for TerminalElement {
//Copied from editor. TODO: move to theme or something //Copied from editor. TODO: move to theme or something
corner_radius: 0.15 * layout.size.line_height, corner_radius: 0.15 * layout.size.line_height,
}; };
hr.paint(bounds, cx.scene); hr.paint(bounds, scene);
} }
} }
}); });
//Draw the text cells //Draw the text cells
cx.paint_layer(clip_bounds, |cx| { scene.paint_layer(clip_bounds, |scene| {
for cell in &layout.cells { for cell in &layout.cells {
cell.paint(origin, layout, visible_bounds, cx); cell.paint(scene, origin, layout, visible_bounds, view, cx);
} }
}); });
//Draw cursor //Draw cursor
if self.cursor_visible { if self.cursor_visible {
if let Some(cursor) = &layout.cursor { if let Some(cursor) = &layout.cursor {
cx.paint_layer(clip_bounds, |cx| { scene.paint_layer(clip_bounds, |scene| {
cursor.paint(origin, cx); cursor.paint(scene, origin, cx);
}) })
} }
} }
if let Some(element) = &mut layout.hyperlink_tooltip { if let Some(element) = &mut layout.hyperlink_tooltip {
element.paint(origin, visible_bounds, cx) Element<TerminalView>::paint(element, scene, origin, visible_bounds, view, cx)
} }
}); });
} }
@ -804,7 +808,7 @@ impl Element for TerminalElement {
fn debug( fn debug(
&self, &self,
_bounds: gpui::geometry::rect::RectF, _bounds: RectF,
_layout: &Self::LayoutState, _layout: &Self::LayoutState,
_paint: &Self::PaintState, _paint: &Self::PaintState,
_cx: &gpui::DebugContext, _cx: &gpui::DebugContext,

View File

@ -236,11 +236,7 @@ impl TerminalView {
cx.notify(); cx.notify();
} }
pub fn should_show_cursor( pub fn should_show_cursor(&self, focused: bool, cx: &mut gpui::ViewContext<'_, Self>) -> bool {
&self,
focused: bool,
cx: &mut gpui::RenderContext<'_, Self>,
) -> bool {
//Don't blink the cursor when not focused, blinking is disabled, or paused //Don't blink the cursor when not focused, blinking is disabled, or paused
if !focused if !focused
|| !self.blinking_on || !self.blinking_on
@ -388,12 +384,12 @@ impl View for TerminalView {
"Terminal" "Terminal"
} }
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox { fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> ElementBox {
let terminal_handle = self.terminal.clone().downgrade(); let terminal_handle = self.terminal.clone().downgrade();
let self_id = cx.view_id(); let self_id = cx.view_id();
let focused = cx let focused = cx
.focused_view_id(cx.window_id()) .focused_view_id()
.filter(|view_id| *view_id == self_id) .filter(|view_id| *view_id == self_id)
.is_some(); .is_some();

View File

@ -11,7 +11,7 @@ use gpui::{
platform, platform,
platform::MouseButton, platform::MouseButton,
scene::MouseClick, scene::MouseClick,
Action, Element, ElementBox, EventContext, MouseState, RenderContext, View, Action, Element, ElementBox, EventContext, MouseState, View, ViewContext,
}; };
use serde::Deserialize; use serde::Deserialize;
@ -27,13 +27,13 @@ pub struct CheckboxStyle {
pub hovered_and_checked: ContainerStyle, pub hovered_and_checked: ContainerStyle,
} }
pub fn checkbox<T: 'static, V: View>( pub fn checkbox<Tag: 'static, V: View>(
label: &'static str, label: &'static str,
style: &CheckboxStyle, style: &CheckboxStyle,
checked: bool, checked: bool,
cx: &mut RenderContext<V>, cx: &mut ViewContext<V>,
change: fn(checked: bool, cx: &mut EventContext) -> (), change: fn(checked: bool, cx: &mut EventContext<V>) -> (),
) -> MouseEventHandler<T> { ) -> MouseEventHandler<Tag, V> {
let label = Label::new(label, style.label.text.clone()) let label = Label::new(label, style.label.text.clone())
.contained() .contained()
.with_style(style.label.container) .with_style(style.label.container)
@ -42,14 +42,14 @@ pub fn checkbox<T: 'static, V: View>(
checkbox_with_label(label, style, checked, cx, change) checkbox_with_label(label, style, checked, cx, change)
} }
pub fn checkbox_with_label<T: 'static, V: View>( pub fn checkbox_with_label<Tag: 'static, V: View>(
label: ElementBox, label: ElementBox<V>,
style: &CheckboxStyle, style: &CheckboxStyle,
checked: bool, checked: bool,
cx: &mut RenderContext<V>, cx: &mut ViewContext<V>,
change: fn(checked: bool, cx: &mut EventContext) -> (), change: fn(checked: bool, cx: &mut EventContext<V>) -> (),
) -> MouseEventHandler<T> { ) -> MouseEventHandler<Tag, V> {
MouseEventHandler::<T>::new(0, cx, |state, _| { MouseEventHandler::new(0, cx, |state, _| {
let indicator = if checked { let indicator = if checked {
svg(&style.icon) svg(&style.icon)
} else { } else {
@ -82,7 +82,7 @@ pub fn checkbox_with_label<T: 'static, V: View>(
.align_children_center() .align_children_center()
.boxed() .boxed()
}) })
.on_click(platform::MouseButton::Left, move |_, cx| { .on_click(platform::MouseButton::Left, move |_, _, cx| {
change(!checked, cx) change(!checked, cx)
}) })
.with_cursor_style(platform::CursorStyle::PointingHand) .with_cursor_style(platform::CursorStyle::PointingHand)
@ -107,7 +107,7 @@ impl Dimensions {
} }
} }
pub fn svg(style: &SvgStyle) -> ConstrainedBox { pub fn svg<V: View>(style: &SvgStyle) -> ConstrainedBox<V> {
Svg::new(style.asset.clone()) Svg::new(style.asset.clone())
.with_color(style.color) .with_color(style.color)
.constrained() .constrained()
@ -121,7 +121,7 @@ pub struct IconStyle {
container: ContainerStyle, container: ContainerStyle,
} }
pub fn icon(style: &IconStyle) -> Container { pub fn icon<V: View>(style: &IconStyle) -> Container<V> {
svg(&style.icon).contained().with_style(style.container) svg(&style.icon).contained().with_style(style.container)
} }
@ -130,8 +130,8 @@ pub fn keystroke_label<V: View>(
label_style: &ContainedText, label_style: &ContainedText,
keystroke_style: &ContainedText, keystroke_style: &ContainedText,
action: Box<dyn Action>, action: Box<dyn Action>,
cx: &mut RenderContext<V>, cx: &mut ViewContext<V>,
) -> Container { ) -> Container<V> {
// FIXME: Put the theme in it's own global so we can // FIXME: Put the theme in it's own global so we can
// query the keystroke style on our own // query the keystroke style on our own
keystroke_label_for( keystroke_label_for(
@ -144,14 +144,14 @@ pub fn keystroke_label<V: View>(
) )
} }
pub fn keystroke_label_for( pub fn keystroke_label_for<V: View>(
window_id: usize, window_id: usize,
view_id: usize, view_id: usize,
label_text: &'static str, label_text: &'static str,
label_style: &ContainedText, label_style: &ContainedText,
keystroke_style: &ContainedText, keystroke_style: &ContainedText,
action: Box<dyn Action>, action: Box<dyn Action>,
) -> Container { ) -> Container<V> {
Flex::row() Flex::row()
.with_child( .with_child(
Label::new(label_text, label_style.text.clone()) Label::new(label_text, label_style.text.clone())
@ -175,37 +175,39 @@ pub fn keystroke_label_for(
pub type ButtonStyle = Interactive<ContainedText>; pub type ButtonStyle = Interactive<ContainedText>;
pub fn cta_button<L, A, V>( pub fn cta_button<Tag, L, A, V>(
label: L, label: L,
action: A, action: A,
max_width: f32, max_width: f32,
style: &ButtonStyle, style: &ButtonStyle,
cx: &mut RenderContext<V>, cx: &mut ViewContext<V>,
) -> ElementBox ) -> ElementBox<V>
where where
Tag: 'static,
L: Into<Cow<'static, str>>, L: Into<Cow<'static, str>>,
A: 'static + Action + Clone, A: 'static + Action + Clone,
V: View, V: View,
{ {
cta_button_with_click(label, max_width, style, cx, move |_, cx| { cta_button_with_click::<Tag, _, _, _>(label, max_width, style, cx, move |_, _, cx| {
cx.dispatch_action(action.clone()) cx.dispatch_action(action.clone())
}) })
.boxed() .boxed()
} }
pub fn cta_button_with_click<L, V, F>( pub fn cta_button_with_click<Tag, L, V, F>(
label: L, label: L,
max_width: f32, max_width: f32,
style: &ButtonStyle, style: &ButtonStyle,
cx: &mut RenderContext<V>, cx: &mut ViewContext<V>,
f: F, f: F,
) -> MouseEventHandler<F> ) -> MouseEventHandler<Tag, V>
where where
Tag: 'static,
L: Into<Cow<'static, str>>, L: Into<Cow<'static, str>>,
V: View, V: View,
F: Fn(MouseClick, &mut EventContext) + 'static, F: Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
{ {
MouseEventHandler::<F>::new(0, cx, |state, _| { MouseEventHandler::<Tag, V>::new(0, cx, |state, _| {
let style = style.style_for(state, false); let style = style.style_for(state, false);
Label::new(label, style.text.to_owned()) Label::new(label, style.text.to_owned())
.aligned() .aligned()
@ -234,16 +236,17 @@ impl ModalStyle {
} }
} }
pub fn modal<V, I, F>( pub fn modal<Tag, V, I, F>(
title: I, title: I,
style: &ModalStyle, style: &ModalStyle,
cx: &mut RenderContext<V>, cx: &mut ViewContext<V>,
build_modal: F, build_modal: F,
) -> ElementBox ) -> ElementBox<V>
where where
Tag: 'static,
V: View, V: View,
I: Into<Cow<'static, str>>, I: Into<Cow<'static, str>>,
F: FnOnce(&mut gpui::RenderContext<V>) -> ElementBox, F: FnOnce(&mut gpui::ViewContext<V>) -> ElementBox<V>,
{ {
const TITLEBAR_HEIGHT: f32 = 28.; const TITLEBAR_HEIGHT: f32 = 28.;
// let active = cx.window_is_active(cx.window_id()); // let active = cx.window_is_active(cx.window_id());
@ -261,11 +264,11 @@ where
) )
.boxed(), .boxed(),
// FIXME: Get a better tag type // FIXME: Get a better tag type
MouseEventHandler::<V>::new(999999, cx, |state, _cx| { MouseEventHandler::<Tag, V>::new(999999, cx, |state, _cx| {
let style = style.close_icon.style_for(state, false); let style = style.close_icon.style_for(state, false);
icon(style).boxed() icon(style).boxed()
}) })
.on_click(platform::MouseButton::Left, move |_, cx| { .on_click(platform::MouseButton::Left, move |_, _, cx| {
let window_id = cx.window_id(); let window_id = cx.window_id();
cx.remove_window(window_id); cx.remove_window(window_id);
}) })

View File

@ -1,7 +1,7 @@
use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
actions, elements::*, AnyViewHandle, AppContext, Element, ElementBox, Entity, MouseState, actions, elements::*, AnyViewHandle, AppContext, Element, ElementBox, Entity, MouseState, View,
RenderContext, View, ViewContext, ViewHandle, ViewContext, ViewHandle,
}; };
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
use settings::{settings_file::SettingsFile, Settings}; use settings::{settings_file::SettingsFile, Settings};
@ -255,7 +255,7 @@ impl View for ThemeSelector {
"ThemeSelector" "ThemeSelector"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
ChildView::new(&self.picker, cx).boxed() ChildView::new(&self.picker, cx).boxed()
} }

View File

@ -2,12 +2,12 @@ use gpui::{
actions, actions,
color::Color, color::Color,
elements::{ elements::{
Canvas, Container, ContainerStyle, Flex, Label, Margin, MouseEventHandler, Padding, Canvas, Container, ContainerStyle, ElementBox, Flex, Label, Margin, MouseEventHandler,
ParentElement, ElementBox, Padding, ParentElement,
}, },
fonts::TextStyle, fonts::TextStyle,
AppContext, Border, Element, Entity, ModelHandle, Quad, RenderContext, Task, View, ViewContext, AppContext, Border, Element, Entity, ModelHandle, Quad, Task, View, ViewContext, ViewHandle,
ViewHandle, WeakViewHandle, WeakViewHandle,
}; };
use project::Project; use project::Project;
use settings::Settings; use settings::Settings;
@ -39,7 +39,7 @@ impl ThemeTestbench {
Flex::row() Flex::row()
.with_children(ramp.iter().cloned().map(|color| { .with_children(ramp.iter().cloned().map(|color| {
Canvas::new(move |bounds, _, cx| { Canvas::new(move |bounds, _, cx| {
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds, bounds,
background: Some(color), background: Some(color),
..Default::default() ..Default::default()
@ -67,7 +67,7 @@ impl ThemeTestbench {
fn render_layer( fn render_layer(
layer_index: usize, layer_index: usize,
layer: &Layer, layer: &Layer,
cx: &mut RenderContext<'_, Self>, cx: &mut ViewContext<'_, Self>,
) -> Container { ) -> Container {
Flex::column() Flex::column()
.with_child( .with_child(
@ -123,7 +123,7 @@ impl ThemeTestbench {
layer_index: usize, layer_index: usize,
set_name: &'static str, set_name: &'static str,
style_set: &StyleSet, style_set: &StyleSet,
cx: &mut RenderContext<'_, Self>, cx: &mut ViewContext<'_, Self>,
) -> Flex { ) -> Flex {
Flex::row() Flex::row()
.with_child(Self::render_button( .with_child(Self::render_button(
@ -182,7 +182,7 @@ impl ThemeTestbench {
text: &'static str, text: &'static str,
style_set: &StyleSet, style_set: &StyleSet,
style_override: Option<fn(&StyleSet) -> &Style>, style_override: Option<fn(&StyleSet) -> &Style>,
cx: &mut RenderContext<'_, Self>, cx: &mut ViewContext<'_, Self>,
) -> ElementBox { ) -> ElementBox {
enum TestBenchButton {} enum TestBenchButton {}
MouseEventHandler::<TestBenchButton>::new(layer_index + button_index, cx, |state, cx| { MouseEventHandler::<TestBenchButton>::new(layer_index + button_index, cx, |state, cx| {
@ -230,7 +230,7 @@ impl ThemeTestbench {
.boxed() .boxed()
} }
fn render_label(text: String, style: &Style, cx: &mut RenderContext<'_, Self>) -> Label { fn render_label(text: String, style: &Style, cx: &mut ViewContext<'_, Self>) -> Label {
let settings = cx.global::<Settings>(); let settings = cx.global::<Settings>();
let font_cache = cx.font_cache(); let font_cache = cx.font_cache();
let family_id = settings.buffer_font_family; let family_id = settings.buffer_font_family;
@ -262,7 +262,7 @@ impl View for ThemeTestbench {
"ThemeTestbench" "ThemeTestbench"
} }
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox { fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> gpui::ElementBox {
let color_scheme = &cx.global::<Settings>().theme.clone().color_scheme; let color_scheme = &cx.global::<Settings>().theme.clone().color_scheme;
Flex::row() Flex::row()

View File

@ -74,7 +74,7 @@ impl View for BaseKeymapSelector {
"BaseKeymapSelector" "BaseKeymapSelector"
} }
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox { fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> gpui::ElementBox {
ChildView::new(&self.picker, cx).boxed() ChildView::new(&self.picker, cx).boxed()
} }

View File

@ -55,7 +55,7 @@ impl View for WelcomePage {
"WelcomePage" "WelcomePage"
} }
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox { fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> ElementBox {
let self_handle = cx.handle(); let self_handle = cx.handle();
let settings = cx.global::<Settings>(); let settings = cx.global::<Settings>();
let theme = settings.theme.clone(); let theme = settings.theme.clone();

View File

@ -9,8 +9,7 @@ use gpui::{
geometry::vector::Vector2F, geometry::vector::Vector2F,
impl_internal_actions, impl_internal_actions,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
AppContext, Border, Element, ElementBox, RenderContext, SizeConstraint, ViewContext, AppContext, Border, Element, ElementBox, SizeConstraint, ViewContext, ViewHandle,
ViewHandle,
}; };
use settings::{DockAnchor, Settings}; use settings::{DockAnchor, Settings};
use theme::Theme; use theme::Theme;
@ -315,7 +314,7 @@ impl Dock {
&self, &self,
theme: &Theme, theme: &Theme,
anchor: DockAnchor, anchor: DockAnchor,
cx: &mut RenderContext<Workspace>, cx: &mut ViewContext<Workspace>,
) -> Option<ElementBox> { ) -> Option<ElementBox> {
let style = &theme.workspace.dock; let style = &theme.workspace.dock;

View File

@ -34,7 +34,7 @@ impl View for ToggleDockButton {
"Dock Toggle" "Dock Toggle"
} }
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox { fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> ElementBox {
let workspace = self.workspace.upgrade(cx); let workspace = self.workspace.upgrade(cx);
if workspace.is_none() { if workspace.is_none() {

View File

@ -740,8 +740,8 @@ pub(crate) mod test {
use super::{Item, ItemEvent}; use super::{Item, ItemEvent};
use crate::{sidebar::SidebarItem, ItemId, ItemNavHistory, Pane, Workspace, WorkspaceId}; use crate::{sidebar::SidebarItem, ItemId, ItemNavHistory, Pane, Workspace, WorkspaceId};
use gpui::{ use gpui::{
elements::Empty, AppContext, Element, ElementBox, Entity, ModelHandle, RenderContext, Task, elements::Empty, AppContext, Element, ElementBox, Entity, ModelHandle, Task, View,
View, ViewContext, ViewHandle, WeakViewHandle, ViewContext, ViewHandle, WeakViewHandle,
}; };
use project::{Project, ProjectEntryId, ProjectPath, WorktreeId}; use project::{Project, ProjectEntryId, ProjectPath, WorktreeId};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -899,7 +899,7 @@ pub(crate) mod test {
"TestItem" "TestItem"
} }
fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, _: &mut ViewContext<Self>) -> ElementBox {
Empty::new().boxed() Empty::new().boxed()
} }
} }

View File

@ -229,7 +229,7 @@ pub mod simple_message_notification {
"MessageNotification" "MessageNotification"
} }
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox { fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> gpui::ElementBox {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
let theme = &theme.simple_message_notification; let theme = &theme.simple_message_notification;

View File

@ -24,8 +24,7 @@ use gpui::{
keymap_matcher::KeymapContext, keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton, NavigationDirection, PromptLevel}, platform::{CursorStyle, MouseButton, NavigationDirection, PromptLevel},
Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext, Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext,
ModelHandle, MouseRegion, Quad, RenderContext, Task, View, ViewContext, ViewHandle, ModelHandle, MouseRegion, Quad, Task, View, ViewContext, ViewHandle, WeakViewHandle,
WeakViewHandle,
}; };
use project::{Project, ProjectEntryId, ProjectPath}; use project::{Project, ProjectEntryId, ProjectPath};
use serde::Deserialize; use serde::Deserialize;
@ -1221,7 +1220,7 @@ impl Pane {
}); });
} }
fn render_tabs(&mut self, cx: &mut RenderContext<Self>) -> impl Element { fn render_tabs(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
let pane = cx.handle(); let pane = cx.handle();
@ -1302,7 +1301,7 @@ impl Pane {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
let detail = detail.clone(); let detail = detail.clone();
move |dragged_item, cx: &mut RenderContext<Workspace>| { move |dragged_item, cx: &mut ViewContext<Workspace>| {
let tab_style = &theme.workspace.tab_bar.dragged_tab; let tab_style = &theme.workspace.tab_bar.dragged_tab;
Self::render_tab( Self::render_tab(
&dragged_item.item, &dragged_item.item,
@ -1384,7 +1383,7 @@ impl Pane {
detail: Option<usize>, detail: Option<usize>,
hovered: bool, hovered: bool,
tab_style: &theme::Tab, tab_style: &theme::Tab,
cx: &mut RenderContext<V>, cx: &mut ViewContext<V>,
) -> ElementBox { ) -> ElementBox {
let title = item.tab_content(detail, &tab_style, cx); let title = item.tab_content(detail, &tab_style, cx);
let mut container = tab_style.container.clone(); let mut container = tab_style.container.clone();
@ -1408,7 +1407,7 @@ impl Pane {
Canvas::new(move |bounds, _, cx| { Canvas::new(move |bounds, _, cx| {
if let Some(color) = icon_color { if let Some(color) = icon_color {
let square = RectF::new(bounds.origin(), vec2f(diameter, diameter)); let square = RectF::new(bounds.origin(), vec2f(diameter, diameter));
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: square, bounds: square,
background: Some(color), background: Some(color),
border: Default::default(), border: Default::default(),
@ -1476,11 +1475,7 @@ impl Pane {
.boxed() .boxed()
} }
fn render_tab_bar_buttons( fn render_tab_bar_buttons(&mut self, theme: &Theme, cx: &mut ViewContext<Self>) -> ElementBox {
&mut self,
theme: &Theme,
cx: &mut RenderContext<Self>,
) -> ElementBox {
Flex::row() Flex::row()
// New menu // New menu
.with_child(render_tab_bar_button( .with_child(render_tab_bar_button(
@ -1529,7 +1524,7 @@ impl Pane {
.boxed() .boxed()
} }
fn render_blank_pane(&mut self, theme: &Theme, _cx: &mut RenderContext<Self>) -> ElementBox { fn render_blank_pane(&mut self, theme: &Theme, _cx: &mut ViewContext<Self>) -> ElementBox {
let background = theme.workspace.background; let background = theme.workspace.background;
Empty::new() Empty::new()
.contained() .contained()
@ -1547,7 +1542,7 @@ impl View for Pane {
"Pane" "Pane"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let this = cx.handle(); let this = cx.handle();
enum MouseNavigationHandler {} enum MouseNavigationHandler {}
@ -1705,7 +1700,7 @@ impl View for Pane {
fn render_tab_bar_button<A: Action + Clone>( fn render_tab_bar_button<A: Action + Clone>(
index: usize, index: usize,
icon: &'static str, icon: &'static str,
cx: &mut RenderContext<Pane>, cx: &mut ViewContext<Pane>,
action: A, action: A,
context_menu: Option<ViewHandle<ContextMenu>>, context_menu: Option<ViewHandle<ContextMenu>>,
) -> ElementBox { ) -> ElementBox {
@ -1853,7 +1848,7 @@ impl PaneBackdrop {
} }
} }
impl Element for PaneBackdrop { impl Element<Pane> for PaneBackdrop {
type LayoutState = (); type LayoutState = ();
type PaintState = (); type PaintState = ();
@ -1861,31 +1856,34 @@ impl Element for PaneBackdrop {
fn layout( fn layout(
&mut self, &mut self,
constraint: gpui::SizeConstraint, constraint: gpui::SizeConstraint,
cx: &mut gpui::LayoutContext, view: &mut Pane,
cx: &mut ViewContext<Pane>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let size = self.child.layout(constraint, cx); let size = self.child.layout(constraint, view, cx);
(size, ()) (size, ())
} }
fn paint( fn paint(
&mut self, &mut self,
scene: &mut gpui::SceneBuilder,
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
_: &mut Self::LayoutState, _: &mut Self::LayoutState,
cx: &mut gpui::PaintContext, view: &mut Pane,
cx: &mut ViewContext<Pane>,
) -> Self::PaintState { ) -> Self::PaintState {
let background = cx.global::<Settings>().theme.editor.background; let background = cx.global::<Settings>().theme.editor.background;
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
cx.scene.push_quad(gpui::Quad { scene.push_quad(gpui::Quad {
bounds: RectF::new(bounds.origin(), bounds.size()), bounds: RectF::new(bounds.origin(), bounds.size()),
background: Some(background), background: Some(background),
..Default::default() ..Default::default()
}); });
let child_view_id = self.child_view; let child_view_id = self.child_view;
cx.scene.push_mouse_region( scene.push_mouse_region(
MouseRegion::new::<Self>(child_view_id, 0, visible_bounds).on_down( MouseRegion::new::<Self>(child_view_id, 0, visible_bounds).on_down(
gpui::platform::MouseButton::Left, gpui::platform::MouseButton::Left,
move |_, cx| { move |_, cx| {
@ -1895,8 +1893,9 @@ impl Element for PaneBackdrop {
), ),
); );
cx.paint_layer(Some(bounds), |cx| { scene.paint_layer(Some(bounds), |scene| {
self.child.paint(bounds.origin(), visible_bounds, cx) self.child
.paint(scene, bounds.origin(), visible_bounds, view, cx)
}) })
} }
@ -1907,9 +1906,10 @@ impl Element for PaneBackdrop {
_visible_bounds: RectF, _visible_bounds: RectF,
_layout: &Self::LayoutState, _layout: &Self::LayoutState,
_paint: &Self::PaintState, _paint: &Self::PaintState,
cx: &gpui::MeasurementContext, view: &V,
cx: &gpui::ViewContext<V>,
) -> Option<RectF> { ) -> Option<RectF> {
self.child.rect_for_text_range(range_utf16, cx) self.child.rect_for_text_range(range_utf16, view, cx)
} }
fn debug( fn debug(
@ -1917,12 +1917,13 @@ impl Element for PaneBackdrop {
_bounds: RectF, _bounds: RectF,
_layout: &Self::LayoutState, _layout: &Self::LayoutState,
_paint: &Self::PaintState, _paint: &Self::PaintState,
cx: &gpui::DebugContext, view: &V,
cx: &gpui::ViewContext<V>,
) -> serde_json::Value { ) -> serde_json::Value {
gpui::json::json!({ gpui::json::json!({
"type": "Pane Back Drop", "type": "Pane Back Drop",
"view": self.child_view, "view": self.child_view,
"child": self.child.debug(cx), "child": self.child.debug(view, cx),
}) })
} }
} }

View File

@ -5,7 +5,7 @@ use gpui::{
geometry::{rect::RectF, vector::Vector2F}, geometry::{rect::RectF, vector::Vector2F},
platform::MouseButton, platform::MouseButton,
scene::MouseUp, scene::MouseUp,
AppContext, Element, ElementBox, EventContext, MouseState, Quad, RenderContext, WeakViewHandle, AppContext, Element, ElementBox, EventContext, MouseState, Quad, ViewContext, WeakViewHandle,
}; };
use project::ProjectEntryId; use project::ProjectEntryId;
use settings::Settings; use settings::Settings;
@ -22,14 +22,14 @@ pub fn dragged_item_receiver<Tag, F>(
drop_index: usize, drop_index: usize,
allow_same_pane: bool, allow_same_pane: bool,
split_margin: Option<f32>, split_margin: Option<f32>,
cx: &mut RenderContext<Pane>, cx: &mut ViewContext<Pane>,
render_child: F, render_child: F,
) -> MouseEventHandler<Tag> ) -> MouseEventHandler<Tag>
where where
Tag: 'static, Tag: 'static,
F: FnOnce(&mut MouseState, &mut RenderContext<Pane>) -> ElementBox, F: FnOnce(&mut MouseState, &mut ViewContext<Pane>) -> ElementBox,
{ {
MouseEventHandler::<Tag>::above(region_id, cx, |state, cx| { MouseEventHandler::<Tag>::above(region_id, cx, |state, _, cx| {
// Observing hovered will cause a render when the mouse enters regardless // Observing hovered will cause a render when the mouse enters regardless
// of if mouse position was accessed before // of if mouse position was accessed before
let drag_position = if state.hovered() { let drag_position = if state.hovered() {
@ -59,7 +59,7 @@ where
.unwrap_or(bounds); .unwrap_or(bounds);
cx.paint_stacking_context(None, None, |cx| { cx.paint_stacking_context(None, None, |cx| {
cx.scene.push_quad(Quad { scene.push_quad(Quad {
bounds: overlay_region, bounds: overlay_region,
background: Some(overlay_color(cx)), background: Some(overlay_color(cx)),
border: Default::default(), border: Default::default(),
@ -102,7 +102,7 @@ pub fn handle_dropped_item(
index: usize, index: usize,
allow_same_pane: bool, allow_same_pane: bool,
split_margin: Option<f32>, split_margin: Option<f32>,
cx: &mut EventContext, cx: &mut ViewContext<Self>,
) { ) {
enum Action { enum Action {
Move(WeakViewHandle<Pane>, usize), Move(WeakViewHandle<Pane>, usize),
@ -110,11 +110,11 @@ pub fn handle_dropped_item(
} }
let drag_and_drop = cx.global::<DragAndDrop<Workspace>>(); let drag_and_drop = cx.global::<DragAndDrop<Workspace>>();
let action = if let Some((_, dragged_item)) = let action = if let Some((_, dragged_item)) =
drag_and_drop.currently_dragged::<DraggedItem>(cx.window_id) drag_and_drop.currently_dragged::<DraggedItem>(cx.window_id())
{ {
Action::Move(dragged_item.pane.clone(), dragged_item.item.id()) Action::Move(dragged_item.pane.clone(), dragged_item.item.id())
} else if let Some((_, project_entry)) = } else if let Some((_, project_entry)) =
drag_and_drop.currently_dragged::<ProjectEntryId>(cx.window_id) drag_and_drop.currently_dragged::<ProjectEntryId>(cx.window_id())
{ {
Action::Open(*project_entry) Action::Open(*project_entry)
} else { } else {

View File

@ -5,7 +5,7 @@ use gpui::{
elements::*, elements::*,
geometry::{rect::RectF, vector::Vector2F}, geometry::{rect::RectF, vector::Vector2F},
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
Axis, Border, ModelHandle, RenderContext, ViewHandle, Axis, Border, ModelHandle, ViewContext, ViewHandle,
}; };
use project::Project; use project::Project;
use serde::Deserialize; use serde::Deserialize;
@ -70,7 +70,7 @@ impl PaneGroup {
follower_states: &FollowerStatesByLeader, follower_states: &FollowerStatesByLeader,
active_call: Option<&ModelHandle<ActiveCall>>, active_call: Option<&ModelHandle<ActiveCall>>,
active_pane: &ViewHandle<Pane>, active_pane: &ViewHandle<Pane>,
cx: &mut RenderContext<Workspace>, cx: &mut ViewContext<Workspace>,
) -> ElementBox { ) -> ElementBox {
self.root.render( self.root.render(
project, project,
@ -131,7 +131,7 @@ impl Member {
follower_states: &FollowerStatesByLeader, follower_states: &FollowerStatesByLeader,
active_call: Option<&ModelHandle<ActiveCall>>, active_call: Option<&ModelHandle<ActiveCall>>,
active_pane: &ViewHandle<Pane>, active_pane: &ViewHandle<Pane>,
cx: &mut RenderContext<Workspace>, cx: &mut ViewContext<Workspace>,
) -> ElementBox { ) -> ElementBox {
enum FollowIntoExternalProject {} enum FollowIntoExternalProject {}
@ -366,7 +366,7 @@ impl PaneAxis {
follower_state: &FollowerStatesByLeader, follower_state: &FollowerStatesByLeader,
active_call: Option<&ModelHandle<ActiveCall>>, active_call: Option<&ModelHandle<ActiveCall>>,
active_pane: &ViewHandle<Pane>, active_pane: &ViewHandle<Pane>,
cx: &mut RenderContext<Workspace>, cx: &mut ViewContext<Workspace>,
) -> ElementBox { ) -> ElementBox {
let last_member_ix = self.members.len() - 1; let last_member_ix = self.members.len() - 1;
Flex::new(self.axis) Flex::new(self.axis)

View File

@ -9,7 +9,7 @@ use gpui::{
elements::*, elements::*,
geometry::{rect::RectF, vector::vec2f}, geometry::{rect::RectF, vector::vec2f},
platform::MouseButton, platform::MouseButton,
AppContext, Entity, RenderContext, Task, View, ViewContext, AppContext, Entity, Task, View, ViewContext,
}; };
use settings::Settings; use settings::Settings;
use smallvec::SmallVec; use smallvec::SmallVec;
@ -64,7 +64,7 @@ impl View for SharedScreen {
"SharedScreen" "SharedScreen"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
enum Focus {} enum Focus {}
let frame = self.frame.clone(); let frame = self.frame.clone();
@ -76,7 +76,7 @@ impl View for SharedScreen {
vec2f(frame.width() as f32, frame.height() as f32), vec2f(frame.width() as f32, frame.height() as f32),
); );
let origin = bounds.origin() + (bounds.size() / 2.) - size / 2.; let origin = bounds.origin() + (bounds.size() / 2.) - size / 2.;
cx.scene.push_surface(gpui::platform::mac::Surface { scene.push_surface(gpui::platform::mac::Surface {
bounds: RectF::new(origin, size), bounds: RectF::new(origin, size),
image_buffer: frame.image(), image_buffer: frame.image(),
}); });

View File

@ -1,7 +1,7 @@
use crate::StatusItemView; use crate::StatusItemView;
use gpui::{ use gpui::{
elements::*, impl_actions, platform::CursorStyle, platform::MouseButton, AnyViewHandle, elements::*, impl_actions, platform::CursorStyle, platform::MouseButton, AnyViewHandle,
AppContext, Entity, RenderContext, Subscription, View, ViewContext, ViewHandle, AppContext, Entity, Subscription, View, ViewContext, ViewHandle,
}; };
use serde::Deserialize; use serde::Deserialize;
use settings::Settings; use settings::Settings;
@ -188,7 +188,7 @@ impl View for Sidebar {
"Sidebar" "Sidebar"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
if let Some(active_item) = self.active_item() { if let Some(active_item) = self.active_item() {
enum ResizeHandleTag {} enum ResizeHandleTag {}
let style = &cx.global::<Settings>().theme.workspace.sidebar; let style = &cx.global::<Settings>().theme.workspace.sidebar;
@ -225,7 +225,7 @@ impl View for SidebarButtons {
"SidebarToggleButton" "SidebarToggleButton"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = &cx.global::<Settings>().theme; let theme = &cx.global::<Settings>().theme;
let tooltip_style = theme.tooltip.clone(); let tooltip_style = theme.tooltip.clone();
let theme = &theme.workspace.status_bar.sidebar_buttons; let theme = &theme.workspace.status_bar.sidebar_buttons;

View File

@ -9,7 +9,7 @@ use gpui::{
}, },
json::{json, ToJson}, json::{json, ToJson},
AnyViewHandle, AppContext, DebugContext, ElementBox, Entity, LayoutContext, MeasurementContext, AnyViewHandle, AppContext, DebugContext, ElementBox, Entity, LayoutContext, MeasurementContext,
PaintContext, RenderContext, SizeConstraint, Subscription, View, ViewContext, ViewHandle, PaintContext, SceneBuilder, SizeConstraint, Subscription, View, ViewContext, ViewHandle,
}; };
use settings::Settings; use settings::Settings;
@ -42,7 +42,7 @@ impl View for StatusBar {
"StatusBar" "StatusBar"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = &cx.global::<Settings>().theme.workspace.status_bar; let theme = &cx.global::<Settings>().theme.workspace.status_bar;
StatusBarElement { StatusBarElement {
@ -143,44 +143,49 @@ struct StatusBarElement {
right: ElementBox, right: ElementBox,
} }
impl Element for StatusBarElement { impl<V: View> Element<V> for StatusBarElement {
type LayoutState = (); type LayoutState = ();
type PaintState = (); type PaintState = ();
fn layout( fn layout(
&mut self, &mut self,
mut constraint: SizeConstraint, mut constraint: SizeConstraint,
cx: &mut LayoutContext, view: &mut V,
cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) { ) -> (Vector2F, Self::LayoutState) {
let max_width = constraint.max.x(); let max_width = constraint.max.x();
constraint.min = vec2f(0., constraint.min.y()); constraint.min = vec2f(0., constraint.min.y());
let right_size = self.right.layout(constraint, cx); let right_size = self.right.layout(constraint, view, cx);
let constraint = SizeConstraint::new( let constraint = SizeConstraint::new(
vec2f(0., constraint.min.y()), vec2f(0., constraint.min.y()),
vec2f(max_width - right_size.x(), constraint.max.y()), vec2f(max_width - right_size.x(), constraint.max.y()),
); );
self.left.layout(constraint, cx); self.left.layout(constraint, view, cx);
(vec2f(max_width, right_size.y()), ()) (vec2f(max_width, right_size.y()), ())
} }
fn paint( fn paint(
&mut self, &mut self,
scene: &mut SceneBuilder,
bounds: RectF, bounds: RectF,
visible_bounds: RectF, visible_bounds: RectF,
_: &mut Self::LayoutState, _: &mut Self::LayoutState,
cx: &mut PaintContext, view: &mut V,
cx: &mut ViewContext<V>,
) -> Self::PaintState { ) -> Self::PaintState {
let origin_y = bounds.upper_right().y(); let origin_y = bounds.upper_right().y();
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
let left_origin = vec2f(bounds.lower_left().x(), origin_y); let left_origin = vec2f(bounds.lower_left().x(), origin_y);
self.left.paint(left_origin, visible_bounds, cx); self.left
.paint(scene, left_origin, visible_bounds, view, cx);
let right_origin = vec2f(bounds.upper_right().x() - self.right.size().x(), origin_y); let right_origin = vec2f(bounds.upper_right().x() - self.right.size().x(), origin_y);
self.right.paint(right_origin, visible_bounds, cx); self.right
.paint(scene, right_origin, visible_bounds, view, cx);
} }
fn rect_for_text_range( fn rect_for_text_range(

View File

@ -1,7 +1,7 @@
use crate::{ItemHandle, Pane}; use crate::{ItemHandle, Pane};
use gpui::{ use gpui::{
elements::*, platform::CursorStyle, platform::MouseButton, Action, AnyViewHandle, AppContext, elements::*, platform::CursorStyle, platform::MouseButton, Action, AnyViewHandle, AppContext,
Entity, RenderContext, View, ViewContext, ElementBox, ViewHandle, WeakViewHandle, ElementBox, Entity, View, ViewContext, ViewHandle, WeakViewHandle,
}; };
use settings::Settings; use settings::Settings;
@ -59,7 +59,7 @@ impl View for Toolbar {
"Toolbar" "Toolbar"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = &cx.global::<Settings>().theme.workspace.toolbar; let theme = &cx.global::<Settings>().theme.workspace.toolbar;
let mut primary_left_items = Vec::new(); let mut primary_left_items = Vec::new();
@ -168,7 +168,7 @@ fn nav_button<A: Action + Clone>(
action: A, action: A,
tooltip_action: A, tooltip_action: A,
action_name: &str, action_name: &str,
cx: &mut RenderContext<Toolbar>, cx: &mut ViewContext<Toolbar>,
) -> ElementBox { ) -> ElementBox {
MouseEventHandler::<A>::new(0, cx, |state, _| { MouseEventHandler::<A>::new(0, cx, |state, _| {
let style = if enabled { let style = if enabled {

View File

@ -45,8 +45,7 @@ use gpui::{
WindowOptions, WindowOptions,
}, },
Action, AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Entity, ModelContext, Action, AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Entity, ModelContext,
ModelHandle, RenderContext, SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle, ModelHandle, SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
WeakViewHandle,
}; };
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem}; use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
use language::LanguageRegistry; use language::LanguageRegistry;
@ -2054,10 +2053,10 @@ impl Workspace {
self.leader_state.followers.contains(&peer_id) self.leader_state.followers.contains(&peer_id)
} }
fn render_titlebar(&self, theme: &Theme, cx: &mut RenderContext<Self>) -> ElementBox { fn render_titlebar(&self, theme: &Theme, cx: &mut ViewContext<Self>) -> ElementBox {
// TODO: There should be a better system in place for this // TODO: There should be a better system in place for this
// (https://github.com/zed-industries/zed/issues/1290) // (https://github.com/zed-industries/zed/issues/1290)
let is_fullscreen = cx.window_is_fullscreen(cx.window_id()); let is_fullscreen = cx.window_is_fullscreen();
let container_theme = if is_fullscreen { let container_theme = if is_fullscreen {
let mut container_theme = theme.workspace.titlebar.container; let mut container_theme = theme.workspace.titlebar.container;
container_theme.padding.left = container_theme.padding.right; container_theme.padding.left = container_theme.padding.right;
@ -2154,7 +2153,7 @@ impl Workspace {
} }
} }
fn render_disconnected_overlay(&self, cx: &mut RenderContext<Workspace>) -> Option<ElementBox> { fn render_disconnected_overlay(&self, cx: &mut ViewContext<Workspace>) -> Option<ElementBox> {
if self.project.read(cx).is_read_only() { if self.project.read(cx).is_read_only() {
enum DisconnectedOverlay {} enum DisconnectedOverlay {}
Some( Some(
@ -2810,7 +2809,7 @@ impl View for Workspace {
"Workspace" "Workspace"
} }
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox { fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let theme = cx.global::<Settings>().theme.clone(); let theme = cx.global::<Settings>().theme.clone();
Stack::new() Stack::new()
.with_child( .with_child(