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,
elements::*,
platform::{CursorStyle, MouseButton},
Action, AppContext, Entity, ModelHandle, RenderContext, View, ViewContext, ViewHandle,
Action, AppContext, Entity, ModelHandle, View, ViewContext, ViewHandle,
};
use language::{LanguageRegistry, LanguageServerBinaryStatus};
use project::{LanguageServerProgress, Project};
@ -172,7 +172,7 @@ impl ActivityIndicator {
.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.
let mut pending_work = self.pending_language_server_work(cx);
if let Some(PendingWork {
@ -314,7 +314,7 @@ impl View for ActivityIndicator {
"ActivityIndicator"
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let Content {
icon,
message,

View File

@ -26,7 +26,7 @@ impl View for 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 = &theme.update_notification;

View File

@ -1,6 +1,6 @@
use gpui::{
elements::*, platform::MouseButton, AppContext, Entity, RenderContext, Subscription, View,
ViewContext, ViewHandle,
elements::*, platform::MouseButton, AppContext, Entity, Subscription, View, ViewContext,
ViewHandle,
};
use itertools::Itertools;
use search::ProjectSearchView;
@ -41,7 +41,7 @@ impl View for 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 {
Some(active_item) => active_item,
None => return Empty::new().boxed(),

View File

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

View File

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

View File

@ -1,7 +1,7 @@
use client::{ContactRequestStatus, User, UserStore};
use gpui::{
elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, RenderContext, Task,
View, ViewContext, ViewHandle,
elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, Task, View,
ViewContext, ViewHandle,
};
use picker::{Picker, PickerDelegate};
use settings::Settings;
@ -32,7 +32,7 @@ impl View for 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()
}

View File

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

View File

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

View File

@ -1,8 +1,8 @@
use crate::{contact_finder::ContactFinder, contact_list::ContactList, ToggleContactsMenu};
use client::UserStore;
use gpui::{
actions, elements::*, platform::MouseButton, AppContext, Entity, ModelHandle, RenderContext,
View, ViewContext, ViewHandle,
actions, elements::*, platform::MouseButton, AppContext, Entity, ModelHandle, View,
ViewContext, ViewHandle,
};
use project::Project;
use settings::Settings;
@ -91,7 +91,7 @@ impl View for 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 child = match &self.child {
Child::ContactList(child) => ChildView::new(child, cx),

View File

@ -37,7 +37,7 @@ impl Element for FacePile {
let mut width = 0.;
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;
@ -60,7 +60,7 @@ impl Element for FacePile {
let size = face.size();
origin_x -= size.x();
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;
}

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@ use gpui::{
color::Color,
elements::{MouseEventHandler, Svg},
platform::{Appearance, MouseButton},
AppContext, Element, ElementBox, Entity, RenderContext, View,
AppContext, Element, ElementBox, Entity, View, ViewContext,
};
use settings::Settings;
@ -40,7 +40,7 @@ impl View for 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 {
Appearance::Light | Appearance::VibrantLight => Color::black(),
Appearance::Dark | Appearance::VibrantDark => Color::white(),

View File

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

View File

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

View File

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

View File

@ -6,8 +6,8 @@ use gpui::{
elements::*,
impl_internal_actions,
platform::{CursorStyle, MouseButton},
AppContext, Element, ElementBox, Entity, MouseState, RenderContext, Subscription, View,
ViewContext, ViewHandle,
AppContext, Element, ElementBox, Entity, MouseState, Subscription, View, ViewContext,
ViewHandle,
};
use settings::{settings_file::SettingsFile, Settings};
use workspace::{
@ -91,7 +91,7 @@ impl View for 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>();
if !settings.enable_copilot_integration {

View File

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

View File

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

View File

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

View File

@ -4,7 +4,7 @@ use super::{
};
use crate::{Anchor, ExcerptId, ExcerptRange, ToPoint as _};
use collections::{Bound, HashMap, HashSet};
use gpui::{fonts::HighlightStyle, RenderContext, ElementBox};
use gpui::{fonts::HighlightStyle, ElementBox, ViewContext};
use language::{BufferSnapshot, Chunk, Patch, Point};
use parking_lot::Mutex;
use std::{
@ -81,7 +81,7 @@ pub enum BlockStyle {
}
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 scroll_x: f32,
pub gutter_width: f32,
@ -933,7 +933,7 @@ impl BlockDisposition {
}
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 {
self.cx

View File

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

View File

@ -31,8 +31,8 @@ use gpui::{
json::{self, ToJson},
platform::{CursorStyle, Modifiers, MouseButton, MouseButtonEvent, MouseMovedEvent},
text_layout::{self, Line, RunStyle, TextLayoutCache},
AppContext, Axis, Border, CursorRegion, Element, ElementBox, EventContext, LayoutContext,
MouseRegion, PaintContext, Quad, SceneBuilder, SizeConstraint, ViewContext, WeakViewHandle,
AppContext, Axis, Border, CursorRegion, Element, ElementBox, MouseRegion, Quad, SceneBuilder,
SizeConstraint, ViewContext, WeakViewHandle,
};
use itertools::Itertools;
use json::json;
@ -124,7 +124,7 @@ impl EditorElement {
cx: &mut PaintContext,
) {
enum EditorElementMouseHandlers {}
cx.scene.push_mouse_region(
scene.push_mouse_region(
MouseRegion::new::<EditorElementMouseHandlers>(view.id(), view.id(), visible_bounds)
.on_down(MouseButton::Left, {
let position_map = position_map.clone();
@ -216,7 +216,7 @@ impl EditorElement {
);
enum GutterHandlers {}
cx.scene.push_mouse_region(
scene.push_mouse_region(
MouseRegion::new::<GutterHandlers>(view.id(), view.id() + 1, gutter_bounds).on_hover(
|hover, cx| {
cx.dispatch_action(GutterHover {
@ -409,7 +409,7 @@ impl EditorElement {
}: MouseMovedEvent,
position_map: &PositionMap,
text_bounds: RectF,
cx: &mut EventContext,
cx: &mut ViewContext<Editor>,
) -> bool {
// 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
@ -432,7 +432,7 @@ impl EditorElement {
precise: bool,
position_map: &PositionMap,
bounds: RectF,
cx: &mut EventContext,
cx: &mut ViewContext<Editor>,
) -> bool {
if !bounds.contains_point(position) {
return false;
@ -465,21 +465,22 @@ impl EditorElement {
fn paint_background(
&self,
scene: &mut SceneBuilder,
gutter_bounds: RectF,
text_bounds: RectF,
layout: &LayoutState,
cx: &mut PaintContext,
cx: &mut ViewContext<Editor>,
) {
let bounds = gutter_bounds.union_rect(text_bounds);
let scroll_top =
layout.position_map.snapshot.scroll_position().y() * layout.position_map.line_height;
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: gutter_bounds,
background: Some(self.style.gutter_background),
border: Border::new(0., Color::transparent_black()),
corner_radius: 0.,
});
cx.scene.push_quad(Quad {
c.push_quad(Quad {
bounds: text_bounds,
background: Some(self.style.background),
border: Border::new(0., Color::transparent_black()),
@ -507,7 +508,7 @@ impl EditorElement {
bounds.width(),
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),
background: Some(self.style.active_line_background),
border: Border::default(),
@ -527,7 +528,7 @@ impl EditorElement {
bounds.width(),
layout.position_map.line_height * highlighted_rows.len() as f32,
);
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: RectF::new(origin, size),
background: Some(self.style.highlighted_line_background),
border: Border::default(),
@ -539,9 +540,11 @@ impl EditorElement {
fn paint_gutter(
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
layout: &mut LayoutState,
editor: &mut Editor,
cx: &mut PaintContext,
) {
let line_height = layout.position_map.line_height;
@ -569,7 +572,7 @@ impl EditorElement {
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;
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;
x += ((layout.gutter_padding + layout.gutter_margin) - indicator.size().x()) / 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_bounds = RectF::new(highlight_origin, highlight_size);
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: highlight_bounds,
background: Some(diff_style.modified),
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_bounds = RectF::new(highlight_origin, highlight_size);
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: highlight_bounds,
background: Some(diff_style.deleted),
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_bounds = RectF::new(highlight_origin, highlight_size);
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: highlight_bounds,
background: Some(color),
border: Border::new(0., Color::transparent_black()),
@ -684,9 +693,11 @@ impl EditorElement {
fn paint_text(
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
layout: &mut LayoutState,
editor: &mut Editor,
cx: &mut PaintContext,
) {
let view = self.view(cx.app);
@ -700,9 +711,9 @@ impl EditorElement {
let content_origin = bounds.origin() + vec2f(layout.gutter_margin, 0.);
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,
style: if !view.link_go_to_definition_state.definitions.is_empty() {
CursorStyle::PointingHand
@ -715,6 +726,7 @@ impl EditorElement {
self.style.folds.ellipses.corner_radius_factor * layout.position_map.line_height;
for (id, range, color) in layout.fold_ranges.iter() {
self.paint_highlighted_range(
scene,
range.clone(),
*color,
fold_corner_radius,
@ -736,7 +748,7 @@ impl EditorElement {
line_end_overshoot,
&layout.position_map,
) {
cx.scene.push_cursor_region(CursorRegion {
scene.push_cursor_region(CursorRegion {
bounds: bound,
style: CursorStyle::PointingHand,
});
@ -747,7 +759,7 @@ impl EditorElement {
.to_point(&layout.position_map.snapshot.display_snapshot)
.row;
cx.scene.push_mouse_region(
scene.push_mouse_region(
MouseRegion::new::<FoldMarkers>(self.view.id(), *id as usize, bound)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(UnfoldAt { buffer_row })
@ -760,6 +772,7 @@ impl EditorElement {
for (range, color) in &layout.highlighted_ranges {
self.paint_highlighted_range(
scene,
range.clone(),
*color,
0.,
@ -781,6 +794,7 @@ impl EditorElement {
for selection in selections {
self.paint_highlighted_range(
scene,
selection.range.clone(),
selection_style.selection,
corner_radius,
@ -858,6 +872,7 @@ impl EditorElement {
for (ix, line) in layout.position_map.line_layouts.iter().enumerate() {
let row = start_row + ix as u32;
line.paint(
scene,
content_origin
+ vec2f(
-scroll_left,
@ -870,14 +885,16 @@ impl EditorElement {
}
}
cx.scene.push_layer(Some(bounds));
for cursor in cursors {
cursor.paint(content_origin, cx);
}
cx.scene.pop_layer();
scene.push_layer(Some(bounds));
scene.paint_layer(Some(bounds), |scene| {
for cursor in cursors {
cursor.paint(scene, content_origin, cx);
}
});
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 =
&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;
@ -897,16 +914,18 @@ impl EditorElement {
}
context_menu.paint(
scene,
list_origin,
RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor
editor,
cx,
);
cx.scene.pop_stacking_context();
scene.pop_stacking_context();
}
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
let hovered_row_layout =
@ -937,8 +956,10 @@ impl EditorElement {
}
hover_popover.paint(
scene,
popover_origin,
RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor
editor,
cx,
);
@ -957,8 +978,10 @@ impl EditorElement {
}
hover_popover.paint(
scene,
popover_origin,
RectF::from_points(Vector2F::zero(), vec2f(f32::MAX, f32::MAX)), // Let content bleed outside of editor
editor,
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 {}
if layout.mode != EditorMode::Full {
return;
@ -1008,13 +1037,13 @@ impl EditorElement {
let thumb_bounds = RectF::from_points(vec2f(left, thumb_top), vec2f(right, thumb_bottom));
if layout.show_scrollbars {
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: track_bounds,
border: style.track.border,
background: style.track.background_color,
..Default::default()
});
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: thumb_bounds,
border: style.thumb.border,
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,
style: CursorStyle::Arrow,
});
cx.scene.push_mouse_region(
scene.push_mouse_region(
MouseRegion::new::<ScrollbarMouseHandlers>(view.id(), view.id(), track_bounds)
.on_move({
let view = view.clone();
@ -1088,6 +1117,7 @@ impl EditorElement {
#[allow(clippy::too_many_arguments)]
fn paint_highlighted_range(
&self,
scene: &mut SceneBuilder,
range: Range<DisplayPoint>,
color: Color,
corner_radius: f32,
@ -1097,7 +1127,7 @@ impl EditorElement {
scroll_top: f32,
scroll_left: f32,
bounds: RectF,
cx: &mut PaintContext,
cx: &mut ViewContext<Self>,
) {
let start_row = layout.visible_display_row_range.start;
let end_row = layout.visible_display_row_range.end;
@ -1141,15 +1171,17 @@ impl EditorElement {
.collect(),
};
highlighted_range.paint(bounds, cx.scene);
highlighted_range.paint(bounds, scene);
}
}
fn paint_blocks(
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
layout: &mut LayoutState,
editor: &mut Editor,
cx: &mut PaintContext,
) {
let scroll_position = layout.position_map.snapshot.scroll_position();
@ -1165,7 +1197,9 @@ impl EditorElement {
if !matches!(block.style, BlockStyle::Sticky) {
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,
line_layouts: &[text_layout::Line],
include_root: bool,
editor: &mut Editor,
cx: &mut LayoutContext,
) -> (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 scroll_x = snapshot.scroll_anchor.offset.x();
let (fixed_blocks, non_fixed_blocks) = snapshot
@ -1542,6 +1571,7 @@ impl EditorElement {
min: Vector2F::zero(),
max: vec2f(width, block.height() as f32 * line_height),
},
editor,
cx,
);
element
@ -1847,6 +1877,7 @@ impl Element for EditorElement {
&style,
&line_layouts,
include_root,
editor,
cx,
);
@ -1924,6 +1955,7 @@ impl Element for EditorElement {
(12. * line_height).min((size.y() - line_height) / 2.),
),
},
editor,
cx,
);
}
@ -1934,6 +1966,7 @@ impl Element for EditorElement {
Axis::Vertical,
line_height * style.code_actions.vertical_scale,
),
editor,
cx,
);
}
@ -2014,7 +2047,7 @@ impl Element for EditorElement {
cx: &mut PaintContext,
) -> Self::PaintState {
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 text_bounds = RectF::new(
@ -2033,20 +2066,20 @@ impl Element for EditorElement {
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. {
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() {
self.paint_blocks(bounds, visible_bounds, layout, cx);
self.paint_blocks(scene, bounds, visible_bounds, layout, editor, cx);
}
self.paint_scrollbar(bounds, layout, cx);
cx.scene.pop_layer();
self.paint_scrollbar(scene, bounds, layout, cx);
scene.pop_layer();
cx.scene.pop_layer();
scene.pop_layer();
}
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 {
CursorShape::Bar => RectF::new(self.origin + origin, vec2f(2.0, self.line_height)),
CursorShape::Block | CursorShape::Hollow => RectF::new(
@ -2269,14 +2302,14 @@ impl Cursor {
//Draw background or border quad
if matches!(self.shape, CursorShape::Hollow) {
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds,
background: None,
border: Border::all(1., self.color),
corner_radius: 0.,
});
} else {
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds,
background: Some(self.color),
border: Default::default(),
@ -2285,7 +2318,7 @@ impl Cursor {
}
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},
impl_internal_actions,
platform::{CursorStyle, MouseButton},
AppContext, Axis, Element, ElementBox, ModelHandle, RenderContext, Task, ViewContext,
AppContext, Axis, Element, ElementBox, ModelHandle, Task, ViewContext,
};
use language::{Bias, DiagnosticEntry, DiagnosticSeverity};
use project::{HoverBlock, Project};
@ -282,7 +282,7 @@ impl HoverState {
snapshot: &EditorSnapshot,
style: &EditorStyle,
visible_rows: Range<u32>,
cx: &mut RenderContext<Editor>,
cx: &mut ViewContext<Editor>,
) -> Option<(DisplayPoint, Vec<ElementBox>)> {
// If there is a diagnostic, position the popovers based on that.
// Otherwise use the start of the hover range
@ -323,7 +323,7 @@ pub struct 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| {
let mut flex = Flex::new(Axis::Vertical).scrollable::<HoverBlock, _>(1, None, cx);
flex.extend(self.contents.iter().map(|content| {
@ -378,7 +378,7 @@ pub struct 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 {}
let mut text_style = style.hover_popover.prose.clone();

View File

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

View File

@ -1,7 +1,7 @@
use gpui::{
elements::*,
platform::{CursorStyle, MouseButton},
Entity, RenderContext, View, ViewContext,
Entity, View, ViewContext,
};
use settings::Settings;
use workspace::{item::ItemHandle, StatusItemView};
@ -27,7 +27,7 @@ impl View for 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 theme = cx.global::<Settings>().theme.clone();
Stack::new()

View File

@ -12,8 +12,8 @@ use gpui::{
actions,
elements::{ChildView, Flex, Label, ParentElement, Svg},
platform::PromptLevel,
serde_json, AnyViewHandle, AppContext, Element, ElementBox, Entity, ModelHandle, RenderContext,
Task, View, ViewContext, ViewHandle,
serde_json, AnyViewHandle, AppContext, Element, ElementBox, Entity, ModelHandle, Task, View,
ViewContext, ViewContext, ViewHandle,
};
use isahc::Request;
use language::Buffer;
@ -232,7 +232,7 @@ impl View for 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()
}

View File

@ -1,7 +1,7 @@
use gpui::{
elements::{Flex, Label, MouseEventHandler, ParentElement, Text},
platform::{CursorStyle, MouseButton},
Element, ElementBox, Entity, RenderContext, View, ViewContext, ViewHandle,
Element, ElementBox, Entity, View, ViewContext, ViewHandle,
};
use settings::Settings;
use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView};
@ -29,7 +29,7 @@ impl View for 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();
Flex::row()

View File

@ -1,7 +1,7 @@
use gpui::{
elements::{Label, MouseEventHandler},
platform::{CursorStyle, MouseButton},
Element, ElementBox, Entity, RenderContext, View, ViewContext, ViewHandle,
Element, ElementBox, Entity, View, ViewContext, ViewHandle,
};
use settings::Settings;
use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView};
@ -29,7 +29,7 @@ impl View for 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();
enum SubmitFeedbackButton {}
MouseEventHandler::<SubmitFeedbackButton>::new(0, cx, |state, _| {

View File

@ -1,7 +1,7 @@
use fuzzy::PathMatch;
use gpui::{
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState,
RenderContext, Task, View, ViewContext, ViewHandle,
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, Task, View,
ViewContext, ViewHandle,
};
use picker::{Picker, PickerDelegate};
use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
@ -50,7 +50,7 @@ impl View for 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()
}

View File

@ -3,7 +3,7 @@ use std::sync::Arc;
use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, DisplayPoint, Editor};
use gpui::{
actions, elements::*, geometry::vector::Vector2F, AnyViewHandle, AppContext, Axis, Entity,
RenderContext, View, ViewContext, ViewHandle,
View, ViewContext, ViewHandle,
};
use menu::{Cancel, Confirm};
use settings::Settings;
@ -156,7 +156,7 @@ impl View for 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 label = format!(

View File

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

View File

@ -69,7 +69,7 @@ pub trait Entity: 'static {
pub trait View: Entity + Sized {
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_out(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
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 SubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut AppContext) -> bool>;
@ -725,11 +725,10 @@ impl AppContext {
let handler = Box::new(
move |view: &mut dyn AnyView,
action: &dyn Action,
cx: &mut AppContext,
window_id: usize,
cx: &mut WindowContext,
view_id: usize| {
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(
view.as_any_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 {
if let Some(focused_view_id) = self.focused_view_id(view.window_id) {
self.ancestors(view.window_id, focused_view_id)
@ -858,57 +863,59 @@ impl AppContext {
self.active_labeled_tasks.values().cloned()
}
// pub fn render_view(&mut self, params: RenderParams) -> Result<ElementBox<Self>> {
// let window_id = params.window_id;
// let view_id = params.view_id;
// let mut view = self
// .views
// .remove(&(window_id, view_id))
// .ok_or_else(|| anyhow!("view not found"))?;
// let element = view.render(params, self);
// self.views.insert((window_id, view_id), view);
// Ok(element)
// }
pub fn render_view(&mut self, params: RenderParams) -> Result<Box<dyn RenderedView>> {
todo!()
// let window_id = params.window_id;
// let view_id = params.view_id;
// let mut view = self
// .views
// .remove(&(window_id, view_id))
// .ok_or_else(|| anyhow!("view not found"))?;
// let element = view.render(params, self);
// self.views.insert((window_id, view_id), view);
// Ok(element)
}
// pub fn render_views(
// &mut self,
// window_id: usize,
// titlebar_height: f32,
// appearance: Appearance,
// ) -> HashMap<usize, ElementBox> {
// self.start_frame();
// #[allow(clippy::needless_collect)]
// let view_ids = self
// .views
// .keys()
// .filter_map(|(win_id, view_id)| {
// if *win_id == window_id {
// Some(*view_id)
// } else {
// None
// }
// })
// .collect::<Vec<_>>();
pub fn render_views(
&mut self,
window_id: usize,
titlebar_height: f32,
appearance: Appearance,
) -> HashMap<usize, Box<dyn RenderedView>> {
todo!()
// self.start_frame();
// #[allow(clippy::needless_collect)]
// let view_ids = self
// .views
// .keys()
// .filter_map(|(win_id, view_id)| {
// if *win_id == window_id {
// Some(*view_id)
// } else {
// None
// }
// })
// .collect::<Vec<_>>();
// view_ids
// .into_iter()
// .map(|view_id| {
// (
// view_id,
// self.render_view(RenderParams {
// window_id,
// view_id,
// titlebar_height,
// hovered_region_ids: Default::default(),
// clicked_region_ids: None,
// refreshing: false,
// appearance,
// })
// .unwrap(),
// )
// })
// .collect()
// }
// view_ids
// .into_iter()
// .map(|view_id| {
// (
// view_id,
// self.render_view(RenderParams {
// window_id,
// view_id,
// titlebar_height,
// hovered_region_ids: Default::default(),
// clicked_region_ids: None,
// refreshing: false,
// appearance,
// })
// .unwrap(),
// )
// })
// .collect()
}
pub(crate) fn start_frame(&mut self) {
self.frame_count += 1;
@ -932,6 +939,7 @@ impl AppContext {
app_context,
window: &mut window,
window_id,
refreshing: false,
};
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,
window_options: WindowOptions,
build_root_view: F,
) -> (usize, ViewHandle<T>)
) -> (usize, ViewHandle<V>)
where
T: View,
F: FnOnce(&mut ViewContext<T>) -> T,
V: View,
F: FnOnce(&mut ViewContext<V>) -> V,
{
self.update(|this| {
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
.open_window(window_id, window_options, this.foreground.clone());
let window =
this.build_window(window_id, root_view.clone().into_any(), platform_window);
let window = this.build_window(window_id, platform_window, build_root_view);
let root_view = window.root_view().clone().downcast::<V>().unwrap();
this.windows.insert(window_id, window);
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
T: View,
F: FnOnce(&mut ViewContext<T>) -> T,
V: View,
F: FnOnce(&mut ViewContext<V>) -> V,
{
self.update(|this| {
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 window =
this.build_window(window_id, root_view.clone().into_any(), platform_window);
let window = this.build_window(window_id, platform_window, build_root_view);
let root_view = window.root_view().clone().downcast::<V>().unwrap();
this.windows.insert(window_id, window);
root_view.update(this, |view, cx| view.focus_in(cx.handle().into_any(), cx));
@ -1563,33 +1564,21 @@ impl AppContext {
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) {
self.windows.remove(&window_id);
self.flush_effects();
}
pub fn build_window(
pub fn build_window<V, F>(
&mut self,
window_id: usize,
root_view: AnyViewHandle,
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();
@ -1653,73 +1642,22 @@ impl AppContext {
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();
window.platform_window.present_scene(scene);
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
T: View,
F: FnOnce(&mut ViewContext<T>) -> T,
S: View,
F: FnOnce(&mut ViewContext<S>) -> S,
{
self.build_and_insert_view(
parent_handle.window_id,
ParentId::View(parent_handle.view_id),
|cx| Some(build_view(cx)),
)
.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
self.update_window(parent.window_id, |cx| {
cx.build_and_insert_view(ParentId::View(parent.view_id), |cx| Some(build_view(cx)))
.unwrap()
})
.unwrap()
}
fn remove_dropped_entities(&mut self) {
@ -1754,7 +1692,7 @@ impl AppContext {
.removed
.push(view_id);
if window.focused_view_id == Some(view_id) {
Some(window.root_view.id())
Some(window.root_view().id())
} else {
None
}
@ -2174,7 +2112,10 @@ impl AppContext {
self.update(|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<_>>() {
cx.update_any_view(focused_id, |view, cx| {
if active {
@ -2254,29 +2195,28 @@ impl AppContext {
if let Some(view_id) = view_id {
this.halt_action_dispatch = false;
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)) {
let type_id = view.as_any().type_id();
if let Some((name, mut handlers)) = this
.actions_mut(capture_phase)
.get_mut(&type_id)
.and_then(|h| h.remove_entry(&action.id()))
{
for handler in handlers.iter_mut().rev() {
this.halt_action_dispatch = true;
handler(view.as_mut(), action, this, window_id, view_id);
if this.halt_action_dispatch {
break;
}
}
this.actions_mut(capture_phase)
this.update_window(window_id, |cx| {
cx.update_any_view(view_id, |view, cx| {
let type_id = view.as_any().type_id();
if let Some((name, mut handlers)) = cx
.actions_mut(capture_phase)
.get_mut(&type_id)
.unwrap()
.insert(name, handlers);
}
this.views.insert((window_id, view_id), view);
}
.and_then(|h| h.remove_entry(&action.id()))
{
for handler in handlers.iter_mut().rev() {
cx.halt_action_dispatch = true;
handler(view, action, cx, view_id);
if cx.halt_action_dispatch {
break;
}
}
cx.actions_mut(capture_phase)
.get_mut(&type_id)
.unwrap()
.insert(name, handlers);
}
})
});
!this.halt_action_dispatch
});
@ -2523,22 +2463,19 @@ impl UpdateView for AppContext {
where
T: View,
{
self.update(|this| {
let mut view = this
.views
.remove(&(handle.window_id, handle.view_id))
.expect("circular view update");
let mut cx = ViewContext::new(this, handle.view_id);
let result = update(
view.as_any_mut()
.downcast_mut()
.expect("downcast is type safe"),
&mut cx,
);
this.views.insert((handle.window_id, handle.view_id), view);
result
self.update_window(handle.window_id, |cx| {
cx.update_any_view(handle.view_id, |view, cx| {
let mut cx = ViewContext::mutable(cx, handle.view_id);
update(
view.as_any_mut()
.downcast_mut()
.expect("downcast is type safe"),
&mut cx,
)
})
.unwrap() // TODO: Are these unwraps safe?
})
.unwrap()
}
}
@ -2877,68 +2814,42 @@ pub trait AnyView {
cx: &mut AppContext,
) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
fn ui_name(&self) -> &'static str;
fn render<'a, 'b>(
&mut self,
params: RenderParams,
cx: &'b mut WindowContext<'a, 'b>,
) -> Box<dyn RenderedView>;
fn render(&mut self, params: RenderParams, cx: &mut WindowContext) -> Box<dyn RenderedView>;
fn focus_in<'a, 'b>(
&mut self,
focused_id: usize,
cx: &'b mut WindowContext<'a, 'b>,
cx: &mut WindowContext<'a, 'b>,
view_id: usize,
);
fn focus_out<'a, 'b>(
&mut self,
focused_id: usize,
cx: &'b mut WindowContext<'a, 'b>,
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>(
fn focus_out(&mut self, focused_id: usize, cx: &mut WindowContext, view_id: usize);
fn key_down(&mut self, event: &KeyDownEvent, cx: &mut WindowContext, view_id: usize) -> bool;
fn key_up(&mut self, event: &KeyUpEvent, cx: &mut WindowContext, view_id: usize) -> bool;
fn modifiers_changed(
&mut self,
event: &ModifiersChangedEvent,
cx: &'b mut WindowContext<'a, 'b>,
cx: &mut WindowContext,
view_id: usize,
) -> bool;
fn keymap_context<'a, 'b>(&self, cx: &'b mut WindowContext<'a, 'b>) -> KeymapContext;
fn debug_json<'a, 'b>(&self, cx: &'b WindowContext<'a, 'b>) -> serde_json::Value;
fn keymap_context(&self, cx: &AppContext) -> KeymapContext;
fn debug_json(&self, cx: &WindowContext) -> serde_json::Value;
fn text_for_range<'a, 'b>(
&self,
range: Range<usize>,
cx: &'b mut WindowContext<'a, 'b>,
) -> Option<String>;
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>(
fn text_for_range(&self, range: Range<usize>, cx: &WindowContext) -> Option<String>;
fn selected_text_range(&self, cx: &WindowContext) -> Option<Range<usize>>;
fn marked_text_range(&self, cx: &WindowContext) -> Option<Range<usize>>;
fn unmark_text(&mut self, cx: &mut WindowContext, view_id: usize);
fn replace_text_in_range(
&mut self,
range: Option<Range<usize>>,
text: &str,
cx: &'b mut WindowContext<'a, 'b>,
cx: &mut WindowContext,
view_id: usize,
);
fn replace_and_mark_text_in_range<'a, 'b>(
fn replace_and_mark_text_in_range(
&mut self,
range: Option<Range<usize>>,
new_text: &str,
new_selected_range: Option<Range<usize>>,
cx: &'b mut WindowContext<'a, 'b>,
cx: &mut WindowContext,
view_id: usize,
);
fn any_handle(&self, window_id: usize, view_id: usize, cx: &AppContext) -> AnyViewHandle {
@ -2978,21 +2889,13 @@ where
T::ui_name()
}
fn render<'a, 'b>(
&mut self,
params: RenderParams,
cx: &mut WindowContext<'a, 'b>,
) -> Box<dyn RenderedView> {
View::render(self, &mut ViewContext::new(params, cx))
fn render(&mut self, params: RenderParams, cx: &mut WindowContext) -> Box<dyn RenderedView> {
todo!()
// Box::new(View::render(self, &mut ViewContext::new(params.view_id, cx)))
}
fn focus_in<'a, 'b>(
&mut self,
cx: &mut WindowContext<'a, 'b>,
view_id: usize,
focused_id: usize,
) {
let mut cx = ViewContext::new(cx, view_id);
fn focus_in(&mut self, focused_id: usize, cx: &mut WindowContext, view_id: usize) {
let mut cx = ViewContext::mutable(cx, view_id);
let focused_view_handle: AnyViewHandle = if view_id == focused_id {
cx.handle().into_any()
} else {
@ -3012,13 +2915,8 @@ where
View::focus_in(self, focused_view_handle, &mut cx);
}
fn focus_out<'a, 'b>(
&mut self,
cx: &mut WindowContext<'a, 'b>,
view_id: usize,
blurred_id: usize,
) {
let mut cx = ViewContext::new(cx, view_id);
fn focus_out(&mut self, blurred_id: usize, cx: &mut WindowContext, view_id: usize) {
let mut cx = ViewContext::mutable(cx, view_id);
let blurred_view_handle: AnyViewHandle = if view_id == blurred_id {
cx.handle().into_any()
} else {
@ -3038,85 +2936,71 @@ where
View::focus_out(self, blurred_view_handle, &mut cx);
}
fn key_down<'a, 'b>(
&mut self,
event: &KeyDownEvent,
cx: &mut WindowContext<'a, 'b>,
view_id: usize,
) -> bool {
let mut cx = ViewContext::new(cx, view_id);
fn key_down(&mut self, event: &KeyDownEvent, cx: &mut WindowContext, view_id: usize) -> bool {
let mut cx = ViewContext::mutable(cx, view_id);
View::key_down(self, event, &mut cx)
}
fn key_up<'a, 'b>(
&mut self,
event: &KeyUpEvent,
cx: &mut WindowContext<'a, 'b>,
view_id: usize,
) -> bool {
let mut cx = ViewContext::new(cx, view_id);
fn key_up(&mut self, event: &KeyUpEvent, cx: &mut WindowContext, view_id: usize) -> bool {
let mut cx = ViewContext::mutable(cx, view_id);
View::key_up(self, event, &mut cx)
}
fn modifiers_changed<'a, 'b>(
fn modifiers_changed(
&mut self,
event: &ModifiersChangedEvent,
cx: &mut WindowContext<'a, 'b>,
cx: &mut WindowContext,
view_id: usize,
) -> bool {
let mut cx = ViewContext::new(cx, view_id);
let mut cx = ViewContext::mutable(cx, view_id);
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)
}
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)
}
fn text_for_range<'a, 'b>(
&self,
range: Range<usize>,
cx: &mut WindowContext<'a, 'b>,
) -> Option<String> {
fn text_for_range(&self, range: Range<usize>, cx: &WindowContext) -> Option<String> {
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)
}
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)
}
fn unmark_text<'a, 'b>(&mut self, cx: &mut WindowContext<'a, 'b>, view_id: usize) {
let mut cx = ViewContext::new(cx, view_id);
fn unmark_text(&mut self, cx: &mut WindowContext, view_id: usize) {
let mut cx = ViewContext::mutable(cx, view_id);
View::unmark_text(self, &mut cx)
}
fn replace_text_in_range<'a, 'b>(
fn replace_text_in_range(
&mut self,
range: Option<Range<usize>>,
text: &str,
cx: &mut WindowContext<'a, 'b>,
cx: &mut WindowContext,
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)
}
fn replace_and_mark_text_in_range<'a, 'b>(
fn replace_and_mark_text_in_range(
&mut self,
range: Option<Range<usize>>,
new_text: &str,
new_selected_range: Option<Range<usize>>,
cx: &mut WindowContext<'a, 'b>,
cx: &mut WindowContext,
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)
}
}
@ -3339,13 +3223,13 @@ impl<M> DerefMut for ModelContext<'_, M> {
}
}
pub struct ViewContext<'a, 'b, T: ?Sized> {
window_context: WindowContext<'a, 'b>,
pub struct ViewContext<'a, 'b, 'c, T: ?Sized> {
window_context: WindowContextRef<'a, 'b, 'c>,
view_id: usize,
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>;
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 {
&mut self.window_context
}
}
impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
fn new(window_context: &'b mut WindowContext<'a, 'b>, view_id: usize) -> Self {
impl<'a, 'b, 'c, V: View> ViewContext<'a, 'b, 'c, V> {
pub(crate) fn mutable(window_context: &'c mut WindowContext<'a, 'b>, view_id: usize) -> 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_type: PhantomData,
}
@ -3425,12 +3317,13 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
}
pub fn focus_self(&mut self) {
self.window_context
.focus(self.window_id, Some(self.view_id));
let window_id = self.window_id;
let view_id = self.view_id;
self.window_context.focus(window_id, Some(view_id));
}
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 {
@ -3444,7 +3337,8 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
}
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)
@ -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>
where
S: View,
F: FnOnce(&mut ViewContext<S>) -> S,
{
self.window_context
.build_and_insert_view(self.window_id, ParentId::View(self.view_id), |cx| {
Some(build_view(cx))
})
.build_and_insert_view(ParentId::View(self.view_id), |cx| Some(build_view(cx)))
.unwrap()
}
@ -3491,11 +3375,8 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
S: View,
F: FnOnce(&mut ViewContext<S>) -> Option<S>,
{
self.window_context.build_and_insert_view(
self.window_id,
ParentId::View(self.view_id),
build_view,
)
self.window_context
.build_and_insert_view(ParentId::View(self.view_id), build_view)
}
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
where
E: Entity,
@ -3637,8 +3501,9 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
F: 'static + FnMut(&mut V, bool, &mut ViewContext<V>),
{
let observer = self.weak_handle();
let window_id = self.window_id;
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) {
observer.update(cx, |observer, 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>),
{
let observer = self.weak_handle();
let window_id = self.window_id;
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) {
observer.update(cx, |observer, cx| {
callback(observer, active, cx);
@ -3680,8 +3546,9 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
) -> bool,
{
let observer = self.weak_handle();
let window_id = self.window_id;
self.window_context.observe_keystrokes(
self.window_id(),
window_id,
move |keystroke, result, handled_by, cx| {
if let Some(observer) = observer.upgrade(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>),
{
let observer = self.weak_handle();
let window_id = self.window_id;
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) {
observer.update(cx, |observer, cx| {
callback(observer, bounds, display, cx);
@ -3740,18 +3608,23 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
}
pub fn notify(&mut self) {
self.window_context
.notify_view(self.window_id, self.view_id);
let window_id = self.window_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) {
let window_id = self.window_id;
let view_id = self.view_id;
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>) {
let window_id = self.window_id;
let view_id = self.view_id;
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>)) {
@ -3813,14 +3686,12 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState {
let region_id = MouseRegionId::new::<Tag>(self.view_id, region_id);
MouseState {
hovered: self.hovered_region_ids.contains(&region_id),
clicked: self.clicked_region_ids.as_ref().and_then(|(ids, button)| {
if ids.contains(&region_id) {
Some(*button)
} else {
None
}
}),
hovered: self.window.hovered_region_ids.contains(&region_id),
clicked: self
.window
.clicked_region_ids
.get(&region_id)
.and_then(|_| self.window.clicked_button),
accessed_hovered: 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>(
&self,
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>> {
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>(
&mut self,
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 {
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>(
&mut self,
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 window_id: usize,
pub view_id: usize,
@ -4686,9 +4590,10 @@ impl<T: 'static> ElementStateHandle<T> {
.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
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 result = f(element_state.downcast_mut().unwrap(), cx);
@ -5104,8 +5009,8 @@ mod tests {
fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox<Self> {
enum Handler {}
let mouse_down_count = self.mouse_down_count.clone();
MouseEventHandler::<Handler>::new(0, cx, |_, _| Empty::new().boxed())
.on_down(MouseButton::Left, move |_, _| {
MouseEventHandler::<Handler, _>::new(0, cx, |_, _| Empty::new().boxed())
.on_down(MouseButton::Left, move |_, _, _| {
mouse_down_count.fetch_add(1, SeqCst);
})
.boxed()
@ -5504,8 +5409,8 @@ mod tests {
});
view.update(cx, |_, c| {
c.observe(&model, |me, observed, c| {
me.events.push(observed.read(c).state.clone())
c.observe(&model, |me, observed, cx| {
me.events.push(observed.read(cx).state.clone())
})
.detach();
});

View File

@ -78,7 +78,11 @@ pub(crate) fn setup_menu_handlers(foreground_platform: &dyn ForegroundPlatform,
move |action| {
let mut cx = cx.borrow_mut();
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);
return;
}

View File

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

View File

@ -1,6 +1,4 @@
use crate::{
app::WindowInvalidation,
elements::Element,
geometry::rect::RectF,
json::{self, ToJson},
keymap_matcher::{Keystroke, MatchResult},
@ -13,8 +11,9 @@ use crate::{
MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene,
},
text_layout::TextLayoutCache,
Action, AnyView, AnyViewHandle, AnyWeakViewHandle, AppContext, ElementBox, MouseRegion,
MouseRegionId, RenderParams, SceneBuilder, View,
util::post_inc,
AnyView, AnyViewHandle, AppContext, Element, ElementBox, MouseRegion, MouseRegionId, ParentId,
RenderParams, SceneBuilder, View, ViewContext, ViewHandle, WindowInvalidation,
};
use anyhow::bail;
use collections::{HashMap, HashSet};
@ -30,8 +29,7 @@ use std::ops::{Deref, DerefMut, Range};
use uuid::Uuid;
pub struct Window {
window_id: usize,
pub(crate) root_view: AnyViewHandle,
pub(crate) root_view: Option<AnyViewHandle>,
pub(crate) focused_view_id: Option<usize>,
pub(crate) is_active: bool,
pub(crate) is_fullscreen: bool,
@ -43,27 +41,29 @@ pub struct Window {
cursor_regions: Vec<CursorRegion>,
mouse_regions: Vec<(MouseRegion, usize)>,
last_mouse_moved_event: Option<Event>,
hovered_region_ids: HashSet<MouseRegionId>,
clicked_region_ids: HashSet<MouseRegionId>,
clicked_button: Option<MouseButton>,
pub(crate) hovered_region_ids: HashSet<MouseRegionId>,
pub(crate) clicked_region_ids: HashSet<MouseRegionId>,
pub(crate) clicked_button: Option<MouseButton>,
mouse_position: Vector2F,
text_layout_cache: TextLayoutCache,
}
impl Window {
pub fn new(
pub fn new<V, F>(
window_id: usize,
root_view: AnyViewHandle,
platform_window: Box<dyn platform::Window>,
cx: &mut AppContext,
) -> Self {
let focused_view_id = Some(root_view.id());
build_view: F,
) -> Self
where
F: FnOnce(&mut ViewContext<V>) -> V,
V: View,
{
let titlebar_height = platform_window.titlebar_height();
let appearance = platform_window.appearance();
Self {
window_id,
root_view,
focused_view_id,
let mut window = Self {
root_view: None,
focused_view_id: None,
is_active: false,
invalidation: None,
is_fullscreen: false,
@ -79,15 +79,30 @@ impl Window {
mouse_position: vec2f(0., 0.),
titlebar_height,
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> {
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_id: usize,
pub refreshing: bool,
pub(crate) refreshing: bool,
}
impl Deref for WindowContext<'_, '_> {
@ -110,16 +125,30 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
app_context,
window,
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
F: FnOnce(&mut dyn AnyView, &mut Self) -> T,
{
let view = self.views.remove(&(self.window_id, view_id))?;
let result = f(view.as_any_mut(), self);
self.views.insert((self.window_id, view_id), view);
let window_id = self.window_id;
let mut view = self.views.remove(&(window_id, view_id))?;
let result = f(view.as_mut(), self);
self.views.insert((window_id, view_id), view);
Some(result)
}
@ -453,8 +482,7 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
//3. Fire region events
let hovered_region_ids = self.window.hovered_region_ids.clone();
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);
if let MouseEvent::Hover(e) = &mut mouse_event {
e.started = hovered_region_ids.contains(&valid_region.id())
@ -473,25 +501,25 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
.handlers
.contains(MouseEvent::down_disc(), Some(e.button));
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.
let mut event_consumed = event_cx.handled;
let mut event_consumed = handled;
if let Some(callbacks) = valid_region.handlers.get(&mouse_event.handler_key()) {
for callback in callbacks {
event_cx.handled = true;
event_cx.with_current_view(valid_region.id().view_id(), {
let region_event = mouse_event.clone();
|cx| callback(region_event, cx)
handled = true;
let view_id = valid_region.id().view_id();
self.update_any_view(view_id, |view, cx| {
handled = callback(mouse_event.clone(), view.as_any_mut(), cx, view_id);
});
event_consumed |= event_cx.handled;
any_event_handled |= event_cx.handled;
event_consumed |= 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.
// 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 {
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
.ancestors(window_id, focused_view_id)
.collect::<Vec<_>>()
@ -645,18 +673,17 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
let window_size = self.window.platform_window.content_size();
let scale_factor = self.window.platform_window.scale_factor();
let root_view_id = self.window.root_view.id();
let rendered_root = self.window.rendered_views.remove(&root_view_id).unwrap();
rendered_root.layout(root_view_id, SizeConstraint::strict(window_size), self);
let root_view_id = self.window.root_view().id();
let mut rendered_root = self.window.rendered_views.remove(&root_view_id).unwrap();
rendered_root.layout(SizeConstraint::strict(window_size), self, root_view_id);
let mut scene_builder = SceneBuilder::new(scale_factor);
let paint_bounds = RectF::from_points(Vector2F::zero(), window_size);
rendered_root.paint(
root_view_id,
&mut scene_builder,
paint_bounds,
paint_bounds,
Vector2F::zero(),
RectF::from_points(Vector2F::zero(), window_size),
self,
root_view_id,
);
self.window.text_layout_cache.finish_frame();
@ -719,14 +746,6 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
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> {
self.window.focused_view_id
}
@ -739,7 +758,7 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
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();
}
@ -763,47 +782,162 @@ impl<'a: 'b, 'b> WindowContext<'a, 'b> {
) -> oneshot::Receiver<usize> {
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 {
fn layout(
&self,
view_id: usize,
&mut self,
constraint: SizeConstraint,
cx: &mut WindowContext,
view_id: usize,
) -> Vector2F;
fn paint(
&self,
view_id: usize,
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
origin: Vector2F,
visible_bounds: RectF,
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> {
fn layout(
&self,
view_id: usize,
&mut self,
constraint: SizeConstraint,
cx: &mut WindowContext,
view_id: usize,
) -> Vector2F {
cx.update_view_for_id(view_id, |view, cx| self.layout(view, constraint, cx))
.unwrap()
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()
}
fn paint(
&self,
view_id: usize,
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
origin: Vector2F,
visible_bounds: RectF,
cx: &mut WindowContext,
view_id: usize,
) {
cx.update_view_for_id(view_id, |view, cx| {
self.paint(view, scene, bounds, visible_bounds, 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::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 {
view: AnyWeakViewHandle,
view_id: usize,
view_name: &'static str,
}
@ -958,94 +1092,101 @@ impl ChildView {
pub fn new(view: &AnyViewHandle, cx: &AppContext) -> Self {
let view_name = cx.view_ui_name(view.window_id(), view.id()).unwrap();
Self {
view: view.downgrade(),
view_id: view.id(),
view_name,
}
}
}
// impl Element for ChildView {
// type LayoutState = bool;
// type PaintState = ();
impl<V: View> Element<V> for ChildView {
type LayoutState = ();
type PaintState = ();
// fn layout(
// &mut self,
// constraint: SizeConstraint,
// cx: &mut LayoutContext,
// ) -> (Vector2F, Self::LayoutState) {
// if cx.rendered_views.contains_key(&self.view.id()) {
// let size = cx.layout(self.view.id(), constraint);
// (size, true)
// } else {
// log::error!(
// "layout called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
// self.view.id(),
// self.view_name
// );
// (Vector2F::zero(), false)
// }
// }
fn layout(
&mut self,
constraint: SizeConstraint,
_: &mut V,
cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) {
if let Some(mut rendered_view) = cx.window.rendered_views.remove(&self.view_id) {
let size = rendered_view.layout(constraint, cx, self.view_id);
cx.window.rendered_views.insert(self.view_id, rendered_view);
(size, ())
} else {
log::error!(
"layout called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
self.view_id,
self.view_name
);
(Vector2F::zero(), ())
}
}
// fn paint(
// &mut self,
// bounds: RectF,
// visible_bounds: RectF,
// view_is_valid: &mut Self::LayoutState,
// cx: &mut PaintContext,
// ) {
// if *view_is_valid {
// cx.paint(self.view.id(), bounds.origin(), visible_bounds);
// } else {
// log::error!(
// "paint called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
// self.view.id(),
// self.view_name
// );
// }
// }
fn paint(
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
_: &mut Self::LayoutState,
_: &mut V,
cx: &mut ViewContext<V>,
) {
if let Some(mut rendered_view) = cx.window.rendered_views.remove(&self.view_id) {
rendered_view.paint(scene, bounds.origin(), visible_bounds, cx, self.view_id);
cx.window.rendered_views.insert(self.view_id, rendered_view);
} else {
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(
// &self,
// range_utf16: Range<usize>,
// _: RectF,
// _: RectF,
// view_is_valid: &Self::LayoutState,
// _: &Self::PaintState,
// cx: &MeasurementContext,
// ) -> Option<RectF> {
// if *view_is_valid {
// cx.rect_for_text_range(self.view.id(), range_utf16)
// } else {
// log::error!(
// "rect_for_text_range called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
// self.view.id(),
// self.view_name
// );
// None
// }
// }
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
_: RectF,
_: RectF,
_: &Self::LayoutState,
_: &Self::PaintState,
_: &V,
cx: &ViewContext<V>,
) -> Option<RectF> {
if let Some(rendered_view) = cx.window.rendered_views.get(&self.view_id) {
rendered_view.rect_for_text_range(range_utf16, &cx.window_context, self.view_id)
} else {
log::error!(
"rect_for_text_range called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
self.view_id,
self.view_name
);
None
}
}
// fn debug(
// &self,
// bounds: RectF,
// _: &Self::LayoutState,
// _: &Self::PaintState,
// cx: &DebugContext,
// ) -> serde_json::Value {
// json!({
// "type": "ChildView",
// "view_id": self.view.id(),
// "bounds": bounds.to_json(),
// "view": if let Some(view) = self.view.upgrade(cx.app) {
// view.debug_json(cx.app)
// } else {
// json!(null)
// },
// "child": if let Some(view) = cx.rendered_views.get(&self.view.id()) {
// view.debug(cx)
// } else {
// json!(null)
// }
// })
// }
// }
fn debug(
&self,
bounds: RectF,
_: &Self::LayoutState,
_: &Self::PaintState,
_: &V,
cx: &ViewContext<V>,
) -> serde_json::Value {
json!({
"type": "ChildView",
"view_id": self.view_id,
"bounds": bounds.to_json(),
"view": if let Some(view) = cx.views.get(&(cx.window_id, self.view_id)) {
view.debug_json(cx)
} else {
json!(null)
},
"child": if let Some(element) = cx.window.rendered_views.get(&self.view_id) {
element.debug(&cx.window_context, self.view_id)
} else {
json!(null)
}
})
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -157,7 +157,7 @@ impl<V: View> Element<V> for ConstrainedBox<V> {
view: &mut V,
cx: &mut ViewContext<V>,
) -> Self::PaintState {
cx.paint_layer(Some(visible_bounds), |cx| {
scene.paint_layer(Some(visible_bounds), |scene| {
self.child
.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() {
cx.scene.push_shadow(scene::Shadow {
scene.push_shadow(scene::Shadow {
bounds: quad_bounds + shadow.offset,
corner_radius: self.style.corner_radius,
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(style) = self.style.cursor {
cx.scene.push_cursor_region(CursorRegion {
scene.push_cursor_region(CursorRegion {
bounds: hit_bounds,
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);
if self.style.border.overlay {
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: quad_bounds,
background: self.style.background_color,
border: Default::default(),
@ -252,16 +252,16 @@ impl<V: View> Element<V> for Container<V> {
self.child
.paint(scene, child_origin, visible_bounds, view, cx);
cx.scene.push_layer(None);
cx.scene.push_quad(Quad {
scene.push_layer(None);
scene.push_quad(Quad {
bounds: quad_bounds,
background: self.style.overlay_color,
border: self.style.border,
corner_radius: self.style.corner_radius,
});
cx.scene.pop_layer();
scene.pop_layer();
} else {
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: quad_bounds,
background: self.style.background_color,
border: self.style.border,
@ -277,14 +277,14 @@ impl<V: View> Element<V> for Container<V> {
.paint(scene, child_origin, visible_bounds, view, cx);
if self.style.overlay_color.is_some() {
cx.scene.push_layer(None);
cx.scene.push_quad(Quad {
scene.push_layer(None);
scene.push_quad(Quad {
bounds: quad_bounds,
background: self.style.overlay_color,
border: Default::default(),
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(
&mut self,
constraint: SizeConstraint,
_: &V,
_: &mut V,
_: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) {
let x = if constraint.max.x().is_finite() && !self.collapsed {
@ -56,6 +56,7 @@ impl<V: View> Element<V> for Empty {
_: RectF,
_: RectF,
_: &mut Self::LayoutState,
_: &mut V,
_: &mut ViewContext<V>,
) -> Self::PaintState {
}

View File

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

View File

@ -73,7 +73,7 @@ impl<V: View> Flex<V> {
remaining_space: &mut f32,
remaining_flex: &mut f32,
cross_axis_max: &mut f32,
view: &V,
view: &mut V,
cx: &mut ViewContext<V>,
) {
let cross_axis = self.axis.invert();
@ -124,7 +124,7 @@ impl<V: View> Element<V> for Flex<V> {
fn layout(
&mut self,
constraint: SizeConstraint,
view: &V,
view: &mut V,
cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) {
let mut total_flex = None;
@ -253,7 +253,7 @@ impl<V: View> Element<V> for Flex<V> {
bounds: RectF,
visible_bounds: RectF,
remaining_space: &mut Self::LayoutState,
view: &V,
view: &mut V,
cx: &mut ViewContext<V>,
) -> Self::PaintState {
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 overflowing = remaining_space < 0.;
if overflowing {
cx.scene.push_layer(Some(visible_bounds));
scene.push_layer(Some(visible_bounds));
}
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)
.on_scroll({
let scroll_state = scroll_state.0.read(cx).clone();
let axis = self.axis;
move |e, cx| {
move |e, _: &mut V, cx| {
if remaining_space < 0. {
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 {
cx.scene.pop_layer();
scene.pop_layer();
}
}
@ -372,7 +372,7 @@ impl<V: View> Element<V> for Flex<V> {
) -> Option<RectF> {
self.children
.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(
@ -431,7 +431,7 @@ impl<V: View> Element<V> for FlexItem<V> {
fn layout(
&mut self,
constraint: SizeConstraint,
view: &V,
view: &mut V,
cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) {
let size = self.child.layout(constraint, view, cx);
@ -444,7 +444,7 @@ impl<V: View> Element<V> for FlexItem<V> {
bounds: RectF,
visible_bounds: RectF,
_: &mut Self::LayoutState,
view: &V,
view: &mut V,
cx: &mut ViewContext<V>,
) -> Self::PaintState {
self.child
@ -474,7 +474,6 @@ impl<V: View> Element<V> for FlexItem<V> {
_: &Self::LayoutState,
_: &Self::PaintState,
view: &V,
cx: &ViewContext<V>,
) -> Value {
json!({

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,8 +7,8 @@ use crate::{
platform::CursorStyle,
platform::MouseButton,
scene::{
CursorRegion, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseHover,
MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut,
CursorRegion, EventContext, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag,
MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut,
},
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
/// region under (or above) it for easy mouse event handling.
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
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 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_click = mouse_state.accessed_clicked();
Self {
@ -57,17 +57,12 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
/// 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
/// gets the opportunity
pub fn above<F>(
region_id: usize,
view: &mut V,
cx: &mut ViewContext<V>,
render_child: F,
) -> Self
pub fn above<F>(region_id: usize, cx: &mut ViewContext<V>, render_child: F) -> Self
where
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
}
@ -82,14 +77,17 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
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
}
pub fn on_move_out(
mut self,
handler: impl Fn(MouseMoveOut, &mut ViewContext<V>) + 'static,
handler: impl Fn(MouseMoveOut, &mut V, &mut EventContext<V>) + 'static,
) -> Self {
self.handlers = self.handlers.on_move_out(handler);
self
@ -98,7 +96,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_down(
mut self,
button: MouseButton,
handler: impl Fn(MouseDown, &mut ViewContext<V>) + 'static,
handler: impl Fn(MouseDown, &mut V, &mut EventContext<V>) + 'static,
) -> Self {
self.handlers = self.handlers.on_down(button, handler);
self
@ -107,7 +105,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_up(
mut self,
button: MouseButton,
handler: impl Fn(MouseUp, &mut ViewContext<V>) + 'static,
handler: impl Fn(MouseUp, &mut V, &mut EventContext<V>) + 'static,
) -> Self {
self.handlers = self.handlers.on_up(button, handler);
self
@ -116,7 +114,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_click(
mut self,
button: MouseButton,
handler: impl Fn(MouseClick, &mut ViewContext<V>) + 'static,
handler: impl Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
) -> Self {
self.handlers = self.handlers.on_click(button, handler);
self
@ -125,7 +123,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_down_out(
mut self,
button: MouseButton,
handler: impl Fn(MouseDownOut, &mut ViewContext<V>) + 'static,
handler: impl Fn(MouseDownOut, &mut V, &mut EventContext<V>) + 'static,
) -> Self {
self.handlers = self.handlers.on_down_out(button, handler);
self
@ -134,7 +132,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_up_out(
mut self,
button: MouseButton,
handler: impl Fn(MouseUpOut, &mut ViewContext<V>) + 'static,
handler: impl Fn(MouseUpOut, &mut V, &mut EventContext<V>) + 'static,
) -> Self {
self.handlers = self.handlers.on_up_out(button, handler);
self
@ -143,20 +141,23 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
pub fn on_drag(
mut self,
button: MouseButton,
handler: impl Fn(MouseDrag, &mut ViewContext<V>) + 'static,
handler: impl Fn(MouseDrag, &mut V, &mut EventContext<V>) + 'static,
) -> Self {
self.handlers = self.handlers.on_drag(button, handler);
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
}
pub fn on_scroll(
mut self,
handler: impl Fn(MouseScrollWheel, &mut ViewContext<V>) + 'static,
handler: impl Fn(MouseScrollWheel, &mut V, &mut EventContext<V>) + 'static,
) -> Self {
self.handlers = self.handlers.on_scroll(handler);
self
@ -191,14 +192,14 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
let hit_bounds = self.hit_bounds(visible_bounds);
if let Some(style) = self.cursor_style {
cx.scene.push_cursor_region(CursorRegion {
scene.push_cursor_region(CursorRegion {
bounds: hit_bounds,
style,
});
}
cx.scene.push_mouse_region(
scene.push_mouse_region(
MouseRegion::from_handlers::<Tag>(
cx.current_view_id(),
cx.view_id(),
self.region_id,
hit_bounds,
self.handlers.clone(),
@ -236,7 +237,7 @@ impl<Tag, V: View> Element<V> for MouseEventHandler<Tag, V> {
self.child
.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);
});
} else {
@ -254,7 +255,7 @@ impl<Tag, V: View> Element<V> for MouseEventHandler<Tag, V> {
_: &Self::LayoutState,
_: &Self::PaintState,
view: &V,
cx: &ViewContext<Self>,
cx: &ViewContext<V>,
) -> Option<RectF> {
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>,
) -> (Vector2F, Self::LayoutState) {
let constraint = if self.anchor_position.is_some() {
SizeConstraint::new(Vector2F::zero(), cx.window_size)
SizeConstraint::new(Vector2F::zero(), cx.window_size())
} else {
constraint
};
@ -137,7 +137,7 @@ impl<V: View> Element<V> for Overlay<V> {
fn paint(
&mut self,
scene: SceneBuilder,
scene: &mut SceneBuilder,
bounds: RectF,
_: RectF,
size: &mut Self::LayoutState,
@ -163,9 +163,9 @@ impl<V: View> Element<V> for Overlay<V> {
OverlayFitMode::SnapToWindow => {
// Snap the horizontal edges of the overlay to the horizontal edges of the window if
// 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();
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);
} else if bounds.min_x() < 0. {
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
// 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();
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);
} else if bounds.min_y() < 0. {
let mut upper_left = bounds.origin();
@ -188,11 +188,11 @@ impl<V: View> Element<V> for Overlay<V> {
OverlayFitMode::SwitchAnchor => {
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);
}
if bounds.max_y() > cx.window_size.y() {
if bounds.max_y() > cx.window_size().y() {
anchor_corner = anchor_corner.switch_axis(Axis::Vertical);
}
@ -212,22 +212,21 @@ impl<V: View> Element<V> for Overlay<V> {
OverlayFitMode::None => {}
}
cx.paint_stacking_context(None, self.z_index, |cx| {
scene.paint_stacking_context(None, self.z_index, |scene| {
if self.hoverable {
enum OverlayHoverCapture {}
// Block hovers in lower stacking contexts
cx.scene
.push_mouse_region(MouseRegion::new::<OverlayHoverCapture>(
cx.current_view_id(),
cx.current_view_id(),
bounds,
));
scene.push_mouse_region(MouseRegion::new::<OverlayHoverCapture>(
cx.view_id(),
cx.view_id(),
bounds,
));
}
self.child.paint(
scene,
bounds.origin(),
RectF::new(Vector2F::zero(), cx.window_size),
RectF::new(Vector2F::zero(), cx.window_size()),
view,
cx,
);

View File

@ -154,32 +154,28 @@ impl<V: View> Element<V> for Resizable<V> {
view: &mut V,
cx: &mut ViewContext<V>,
) -> 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);
enum ResizeHandle {}
cx.scene.push_mouse_region(
MouseRegion::new::<ResizeHandle>(
cx.current_view_id(),
self.side as usize,
handle_region,
)
.on_down(MouseButton::Left, |_, _| {}) // This prevents the mouse down event from being propagated elsewhere
.on_drag(MouseButton::Left, {
let state = self.state.clone();
let side = self.side;
move |e, cx| {
let prev_width = state.actual_dimension.get();
state
.custom_dimension
.set(0f32.max(prev_width + side.compute_delta(e)).round());
cx.notify();
}
}),
scene.push_mouse_region(
MouseRegion::new::<ResizeHandle>(cx.view_id(), self.side as usize, handle_region)
.on_down(MouseButton::Left, |_, _: &mut V, _| {}) // This prevents the mouse down event from being propagated elsewhere
.on_drag(MouseButton::Left, {
let state = self.state.clone();
let side = self.side;
move |e, _: &mut V, cx| {
let prev_width = state.actual_dimension.get();
state
.custom_dimension
.set(0f32.max(prev_width + side.compute_delta(e)).round());
cx.notify();
}
}),
);
cx.scene.push_cursor_region(crate::CursorRegion {
scene.push_cursor_region(crate::CursorRegion {
bounds: handle_region,
style: match self.side.axis() {
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
.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.
/// The first child determines the size of the others.
#[derive(Default)]
pub struct Stack<V: View> {
children: Vec<ElementBox<V>>,
}
impl<V: View> Default for Stack<V> {
fn default() -> Self {
Self {
children: Vec::new(),
}
}
}
impl<V: View> Stack<V> {
pub fn new() -> Self {
Self::default()
@ -53,7 +60,7 @@ impl<V: View> Element<V> for Stack<V> {
cx: &mut ViewContext<V>,
) -> Self::PaintState {
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);
});
}

View File

@ -37,7 +37,7 @@ impl<V: View> Element<V> for Svg {
fn layout(
&mut self,
constraint: SizeConstraint,
view: &mut V,
_: &mut V,
cx: &mut ViewContext<V>,
) -> (Vector2F, Self::LayoutState) {
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(
chunks,
&self.style,
cx.text_layout_cache,
cx.text_layout_cache(),
&cx.font_cache,
usize::MAX,
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.
pub fn layout_highlighted_chunks<'a>(
chunks: impl Iterator<Item = (&'a str, Option<HighlightStyle>)>,
text_style: &'a TextStyle,
text_layout_cache: &'a TextLayoutCache,
font_cache: &'a Arc<FontCache>,
text_style: &TextStyle,
text_layout_cache: &TextLayoutCache,
font_cache: &Arc<FontCache>,
max_line_len: usize,
max_line_count: usize,
) -> Vec<Line> {
@ -276,26 +276,22 @@ pub fn layout_highlighted_chunks<'a>(
#[cfg(test)]
mod tests {
use super::*;
use crate::{
elements::Empty, fonts, platform, AppContext, ElementBox, Entity, View, ViewContext,
};
use crate::{elements::Empty, fonts, AppContext, ElementBox, Entity, View, ViewContext};
#[crate::test(self)]
fn test_soft_wrapping_with_carriage_returns(cx: &mut AppContext) {
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(), || {
let mut text = Text::new("Hello\r\n", Default::default()).with_soft_wrap(true);
let (_, state) = text.layout(
SizeConstraint::new(Default::default(), vec2f(f32::INFINITY, f32::INFINITY)),
&mut presenter.build_layout_context(Default::default(), false, cx),
);
assert_eq!(state.shaped_lines.len(), 2);
assert_eq!(state.wrap_boundaries.len(), 2);
root_view.update(cx, |view, cx| {
let mut text = Text::new("Hello\r\n", Default::default()).with_soft_wrap(true);
let (_, state) = text.layout(
SizeConstraint::new(Default::default(), vec2f(f32::INFINITY, f32::INFINITY)),
view,
cx,
);
assert_eq!(state.shaped_lines.len(), 2);
assert_eq!(state.wrap_boundaries.len(), 2);
});
});
}

View File

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

View File

@ -6,7 +6,6 @@ use crate::{
},
json::{self, json},
platform::ScrollWheelEvent,
scene::MouseScrollWheel,
ElementBox, MouseRegion, SceneBuilder, View, ViewContext,
};
use json::ToJson;
@ -47,7 +46,7 @@ pub struct UniformList<V: View> {
state: UniformListState,
item_count: usize,
#[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_bottom: f32,
get_width_from_item: Option<usize>,
@ -63,19 +62,12 @@ impl<V: View> UniformList<V> {
) -> Self
where
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 {
state,
item_count,
append_items: Box::new(move |range, items, cx| {
if let Some(handle) = handle.upgrade(cx) {
cx.render(&handle, |view, cx| {
append_items(view, range, items, cx);
});
}
}),
append_items: Box::new(append_items),
padding_top: 0.,
padding_bottom: 0.,
get_width_from_item: None,
@ -194,18 +186,18 @@ impl<V: View> Element<V> for UniformList<V> {
let sample_item_ix;
let sample_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;
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());
sample_item = item;
} else {
return no_items;
}
} else {
(self.append_items)(0..1, &mut items, cx);
(self.append_items)(view, 0..1, &mut items, cx);
sample_item_ix = 0;
if let Some(mut item) = items.pop() {
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(), f32::INFINITY),
),
view,
cx,
);
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 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);
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 {
(self.append_items)(start..end, &mut items, cx);
(self.append_items)(view, start..end, &mut items, cx);
}
for item in &mut items {
@ -289,20 +282,16 @@ impl<V: View> Element<V> for UniformList<V> {
) -> Self::PaintState {
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({
let scroll_max = layout.scroll_max;
let state = self.state.clone();
move |MouseScrollWheel {
platform_event:
ScrollWheelEvent {
position, delta, ..
},
..
},
cx| {
move |event, _, cx| {
let ScrollWheelEvent {
position, delta, ..
} = event.platform_event;
if !Self::scroll(
state.clone(),
position,
@ -328,7 +317,7 @@ impl<V: View> Element<V> for UniformList<V> {
item_origin += vec2f(0.0, layout.item_height);
}
cx.scene.pop_layer();
scene.pop_layer();
}
fn rect_for_text_range(

View File

@ -15,7 +15,9 @@ pub use clipboard::ClipboardItem;
pub mod fonts;
pub mod geometry;
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 use text_layout::TextLayoutCache;
mod util;

View File

@ -236,6 +236,19 @@ impl SceneBuilder {
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>) {
let z_index = z_index.unwrap_or_else(|| self.active_stacking_context().z_index + 1);
self.active_stacking_context_stack
@ -249,6 +262,15 @@ impl SceneBuilder {
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>) {
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;
@ -63,7 +69,7 @@ impl MouseRegion {
pub fn on_down<V, F>(mut self, button: MouseButton, handler: F) -> Self
where
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
@ -72,7 +78,7 @@ impl MouseRegion {
pub fn on_up<V, F>(mut self, button: MouseButton, handler: F) -> Self
where
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
@ -81,7 +87,7 @@ impl MouseRegion {
pub fn on_click<V, F>(mut self, button: MouseButton, handler: F) -> Self
where
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
@ -90,7 +96,7 @@ impl MouseRegion {
pub fn on_down_out<V, F>(mut self, button: MouseButton, handler: F) -> Self
where
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
@ -99,7 +105,7 @@ impl MouseRegion {
pub fn on_up_out<V, F>(mut self, button: MouseButton, handler: F) -> Self
where
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
@ -108,7 +114,7 @@ impl MouseRegion {
pub fn on_drag<V, F>(mut self, button: MouseButton, handler: F) -> Self
where
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
@ -117,7 +123,7 @@ impl MouseRegion {
pub fn on_hover<V, F>(mut self, handler: F) -> Self
where
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
@ -126,7 +132,7 @@ impl MouseRegion {
pub fn on_move<V, F>(mut self, handler: F) -> Self
where
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
@ -135,7 +141,7 @@ impl MouseRegion {
pub fn on_move_out<V, F>(mut self, handler: F) -> Self
where
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
@ -144,7 +150,7 @@ impl MouseRegion {
pub fn on_scroll<V, F>(mut self, handler: F) -> Self
where
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
@ -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)]
pub struct HandlerKey {
@ -221,41 +259,41 @@ impl HandlerSet {
set.insert(
HandlerKey::new(MouseEvent::move_disc(), None),
SmallVec::from_buf([Rc::new(|_, _| {})]),
SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
);
set.insert(
HandlerKey::new(MouseEvent::hover_disc(), None),
SmallVec::from_buf([Rc::new(|_, _| {})]),
SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
);
for button in MouseButton::all() {
set.insert(
HandlerKey::new(MouseEvent::drag_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]),
SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
);
set.insert(
HandlerKey::new(MouseEvent::down_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]),
SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
);
set.insert(
HandlerKey::new(MouseEvent::up_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]),
SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
);
set.insert(
HandlerKey::new(MouseEvent::click_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]),
SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
);
set.insert(
HandlerKey::new(MouseEvent::down_out_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]),
SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
);
set.insert(
HandlerKey::new(MouseEvent::up_out_disc(), Some(button)),
SmallVec::from_buf([Rc::new(|_, _| {})]),
SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
);
}
set.insert(
HandlerKey::new(MouseEvent::scroll_wheel_disc(), None),
SmallVec::from_buf([Rc::new(|_, _| {})]),
SmallVec::from_buf([Rc::new(|_, _, _, _| false)]),
);
HandlerSet { set }
@ -296,12 +334,16 @@ impl HandlerSet {
pub fn on_move<V, F>(mut self, handler: F) -> Self
where
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,
Rc::new(move |region_event, cx| {
Rc::new(move |region_event, view, cx, view_id| {
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 {
panic!(
"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
where
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,
Rc::new(move |region_event, cx| {
Rc::new(move |region_event, view, cx, view_id| {
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 {
panic!(
"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
where
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),
Rc::new(move |region_event, cx| {
Rc::new(move |region_event, view, cx, view_id| {
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 {
panic!(
"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
where
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),
Rc::new(move |region_event, cx| {
Rc::new(move |region_event, view, cx, view_id| {
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 {
panic!(
"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
where
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),
Rc::new(move |region_event, cx| {
Rc::new(move |region_event, view, cx, view_id| {
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 {
panic!(
"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
where
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),
Rc::new(move |region_event, cx| {
Rc::new(move |region_event, view, cx, view_id| {
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 {
panic!(
"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
where
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),
Rc::new(move |region_event, cx| {
Rc::new(move |region_event, view, cx, view_id| {
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 {
panic!(
"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
where
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),
Rc::new(move |region_event, cx| {
Rc::new(move |region_event, view, cx, view_id| {
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 {
panic!(
"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
where
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,
Rc::new(move |region_event, cx| {
Rc::new(move |region_event, view, cx, view_id| {
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 {
panic!(
"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
where
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,
Rc::new(move |region_event, cx| {
Rc::new(move |region_event, view, cx, view_id| {
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 {
panic!(
"Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::ScrollWheel, found {:?}",

View File

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

View File

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

View File

@ -2,7 +2,7 @@ use editor::Editor;
use gpui::{
elements::*,
platform::{CursorStyle, MouseButton},
Entity, RenderContext, Subscription, View, ViewContext, ViewHandle,
Entity, Subscription, View, ViewContext, ViewHandle,
};
use settings::Settings;
use std::sync::Arc;
@ -50,7 +50,7 @@ impl View for 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() {
let active_language_text = if let Some(active_language_text) = active_language {
active_language_text.to_string()

View File

@ -4,8 +4,8 @@ pub use active_buffer_language::ActiveBufferLanguage;
use editor::Editor;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState,
RenderContext, View, ViewContext, ViewHandle,
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, View,
ViewContext, ViewHandle,
};
use language::{Buffer, LanguageRegistry};
use picker::{Picker, PickerDelegate};
@ -120,7 +120,7 @@ impl View for 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()
}

View File

@ -5,7 +5,7 @@ use editor::{
use fuzzy::StringMatch;
use gpui::{
actions, elements::*, geometry::vector::Vector2F, AnyViewHandle, AppContext, Entity,
MouseState, RenderContext, Task, View, ViewContext, ViewHandle,
MouseState, Task, View, ViewContext, ViewHandle,
};
use language::Outline;
use ordered_float::OrderedFloat;
@ -48,7 +48,7 @@ impl View for 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()
}

View File

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

View File

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

View File

@ -4,8 +4,8 @@ use editor::{
};
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState,
RenderContext, Task, View, ViewContext, ViewHandle,
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MouseState, Task, View,
ViewContext, ViewHandle,
};
use ordered_float::OrderedFloat;
use picker::{Picker, PickerDelegate};
@ -48,7 +48,7 @@ impl View for 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()
}

View File

@ -4,8 +4,7 @@ use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
actions,
elements::{ChildView, Flex, ParentElement},
AnyViewHandle, AppContext, Element, ElementBox, Entity, RenderContext, Task, View, ViewContext,
ViewHandle,
AnyViewHandle, AppContext, Element, ElementBox, Entity, Task, View, ViewContext, ViewHandle,
};
use highlighted_workspace_location::HighlightedWorkspaceLocation;
use ordered_float::OrderedFloat;
@ -102,7 +101,7 @@ impl View for 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()
}

View File

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

View File

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

View File

@ -3,8 +3,8 @@ use gpui::{
elements::*,
impl_internal_actions,
platform::{CursorStyle, MouseButton},
AppContext, Element, ElementBox, Entity, RenderContext, View, ViewContext, ViewHandle,
WeakModelHandle, WeakViewHandle,
AppContext, Element, ElementBox, Entity, View, ViewContext, ViewHandle, WeakModelHandle,
WeakViewHandle,
};
use settings::Settings;
use std::any::TypeId;
@ -42,14 +42,14 @@ impl View for 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 project = match workspace {
Some(workspace) => workspace.read(cx).project().read(cx),
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
.map(|view_id| {
cx.view_type_id(cx.window_id(), view_id) == Some(TypeId::of::<TerminalView>())

View File

@ -10,8 +10,8 @@ use gpui::{
platform::{CursorStyle, MouseButton},
serde_json::json,
text_layout::{Line, RunStyle},
Element, ElementBox, EventContext, FontCache, ModelContext, MouseRegion, PaintContext, Quad,
SizeConstraint, TextLayoutCache, WeakModelHandle, WeakViewHandle,
Element, ElementBox, EventContext, FontCache, ModelContext, MouseRegion, Quad, SceneBuilder,
SizeConstraint, TextLayoutCache, ViewContext, WeakModelHandle, WeakViewHandle,
};
use itertools::Itertools;
use language::CursorShape;
@ -45,7 +45,7 @@ pub struct LayoutState {
size: TerminalSize,
mode: TermMode,
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
@ -84,10 +84,12 @@ impl LayoutCell {
fn paint(
&self,
scene: &mut SceneBuilder,
origin: Vector2F,
layout: &LayoutState,
visible_bounds: RectF,
cx: &mut PaintContext,
view: &mut TerminalView,
cx: &mut ViewContext<TerminalView>,
) {
let pos = {
let point = self.point;
@ -98,7 +100,7 @@ impl LayoutCell {
};
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,
);
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: RectF::new(position, size),
background: Some(self.color),
border: Default::default(),
@ -380,7 +382,7 @@ impl TerminalElement {
view_id: usize,
visible_bounds: RectF,
mode: TermMode,
cx: &mut PaintContext,
cx: &mut ViewContext<TerminalView>,
) {
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.
@ -553,7 +555,8 @@ impl Element for TerminalElement {
fn layout(
&mut self,
constraint: gpui::SizeConstraint,
cx: &mut gpui::LayoutContext,
view: &mut TerminalView,
cx: &mut ViewContext<TerminalView>,
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
let settings = cx.global::<Settings>();
let font_cache = cx.font_cache();
@ -717,23 +720,24 @@ impl Element for TerminalElement {
fn paint(
&mut self,
bounds: gpui::geometry::rect::RectF,
visible_bounds: gpui::geometry::rect::RectF,
scene: &mut SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
layout: &mut Self::LayoutState,
cx: &mut gpui::PaintContext,
cx: &mut ViewContext<TerminalView>,
) -> Self::PaintState {
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
//Setup element stuff
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.);
// 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);
cx.scene.push_cursor_region(gpui::CursorRegion {
scene.push_cursor_region(gpui::CursorRegion {
bounds,
style: if layout.hyperlink_tooltip.is_some() {
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
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: RectF::new(bounds.origin(), bounds.size()),
background: Some(layout.background_color),
border: Default::default(),
@ -757,7 +761,7 @@ impl Element for TerminalElement {
});
//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()
{
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
corner_radius: 0.15 * layout.size.line_height,
};
hr.paint(bounds, cx.scene);
hr.paint(bounds, scene);
}
}
});
//Draw the text cells
cx.paint_layer(clip_bounds, |cx| {
scene.paint_layer(clip_bounds, |scene| {
for cell in &layout.cells {
cell.paint(origin, layout, visible_bounds, cx);
cell.paint(scene, origin, layout, visible_bounds, view, cx);
}
});
//Draw cursor
if self.cursor_visible {
if let Some(cursor) = &layout.cursor {
cx.paint_layer(clip_bounds, |cx| {
cursor.paint(origin, cx);
scene.paint_layer(clip_bounds, |scene| {
cursor.paint(scene, origin, cx);
})
}
}
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(
&self,
_bounds: gpui::geometry::rect::RectF,
_bounds: RectF,
_layout: &Self::LayoutState,
_paint: &Self::PaintState,
_cx: &gpui::DebugContext,

View File

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

View File

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

View File

@ -1,7 +1,7 @@
use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{
actions, elements::*, AnyViewHandle, AppContext, Element, ElementBox, Entity, MouseState,
RenderContext, View, ViewContext, ViewHandle,
actions, elements::*, AnyViewHandle, AppContext, Element, ElementBox, Entity, MouseState, View,
ViewContext, ViewHandle,
};
use picker::{Picker, PickerDelegate};
use settings::{settings_file::SettingsFile, Settings};
@ -255,7 +255,7 @@ impl View for 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()
}

View File

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

View File

@ -74,7 +74,7 @@ impl View for 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()
}

View File

@ -55,7 +55,7 @@ impl View for 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 settings = cx.global::<Settings>();
let theme = settings.theme.clone();

View File

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

View File

@ -34,7 +34,7 @@ impl View for ToggleDockButton {
"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);
if workspace.is_none() {

View File

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

View File

@ -229,7 +229,7 @@ pub mod simple_message_notification {
"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 = &theme.simple_message_notification;

View File

@ -24,8 +24,7 @@ use gpui::{
keymap_matcher::KeymapContext,
platform::{CursorStyle, MouseButton, NavigationDirection, PromptLevel},
Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext,
ModelHandle, MouseRegion, Quad, RenderContext, Task, View, ViewContext, ViewHandle,
WeakViewHandle,
ModelHandle, MouseRegion, Quad, Task, View, ViewContext, ViewHandle, WeakViewHandle,
};
use project::{Project, ProjectEntryId, ProjectPath};
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 pane = cx.handle();
@ -1302,7 +1301,7 @@ impl Pane {
let theme = cx.global::<Settings>().theme.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;
Self::render_tab(
&dragged_item.item,
@ -1384,7 +1383,7 @@ impl Pane {
detail: Option<usize>,
hovered: bool,
tab_style: &theme::Tab,
cx: &mut RenderContext<V>,
cx: &mut ViewContext<V>,
) -> ElementBox {
let title = item.tab_content(detail, &tab_style, cx);
let mut container = tab_style.container.clone();
@ -1408,7 +1407,7 @@ impl Pane {
Canvas::new(move |bounds, _, cx| {
if let Some(color) = icon_color {
let square = RectF::new(bounds.origin(), vec2f(diameter, diameter));
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: square,
background: Some(color),
border: Default::default(),
@ -1476,11 +1475,7 @@ impl Pane {
.boxed()
}
fn render_tab_bar_buttons(
&mut self,
theme: &Theme,
cx: &mut RenderContext<Self>,
) -> ElementBox {
fn render_tab_bar_buttons(&mut self, theme: &Theme, cx: &mut ViewContext<Self>) -> ElementBox {
Flex::row()
// New menu
.with_child(render_tab_bar_button(
@ -1529,7 +1524,7 @@ impl Pane {
.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;
Empty::new()
.contained()
@ -1547,7 +1542,7 @@ impl View for Pane {
"Pane"
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
let this = cx.handle();
enum MouseNavigationHandler {}
@ -1705,7 +1700,7 @@ impl View for Pane {
fn render_tab_bar_button<A: Action + Clone>(
index: usize,
icon: &'static str,
cx: &mut RenderContext<Pane>,
cx: &mut ViewContext<Pane>,
action: A,
context_menu: Option<ViewHandle<ContextMenu>>,
) -> ElementBox {
@ -1853,7 +1848,7 @@ impl PaneBackdrop {
}
}
impl Element for PaneBackdrop {
impl Element<Pane> for PaneBackdrop {
type LayoutState = ();
type PaintState = ();
@ -1861,31 +1856,34 @@ impl Element for PaneBackdrop {
fn layout(
&mut self,
constraint: gpui::SizeConstraint,
cx: &mut gpui::LayoutContext,
view: &mut Pane,
cx: &mut ViewContext<Pane>,
) -> (Vector2F, Self::LayoutState) {
let size = self.child.layout(constraint, cx);
let size = self.child.layout(constraint, view, cx);
(size, ())
}
fn paint(
&mut self,
scene: &mut gpui::SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
_: &mut Self::LayoutState,
cx: &mut gpui::PaintContext,
view: &mut Pane,
cx: &mut ViewContext<Pane>,
) -> Self::PaintState {
let background = cx.global::<Settings>().theme.editor.background;
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()),
background: Some(background),
..Default::default()
});
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(
gpui::platform::MouseButton::Left,
move |_, cx| {
@ -1895,8 +1893,9 @@ impl Element for PaneBackdrop {
),
);
cx.paint_layer(Some(bounds), |cx| {
self.child.paint(bounds.origin(), visible_bounds, cx)
scene.paint_layer(Some(bounds), |scene| {
self.child
.paint(scene, bounds.origin(), visible_bounds, view, cx)
})
}
@ -1907,9 +1906,10 @@ impl Element for PaneBackdrop {
_visible_bounds: RectF,
_layout: &Self::LayoutState,
_paint: &Self::PaintState,
cx: &gpui::MeasurementContext,
view: &V,
cx: &gpui::ViewContext<V>,
) -> Option<RectF> {
self.child.rect_for_text_range(range_utf16, cx)
self.child.rect_for_text_range(range_utf16, view, cx)
}
fn debug(
@ -1917,12 +1917,13 @@ impl Element for PaneBackdrop {
_bounds: RectF,
_layout: &Self::LayoutState,
_paint: &Self::PaintState,
cx: &gpui::DebugContext,
view: &V,
cx: &gpui::ViewContext<V>,
) -> serde_json::Value {
gpui::json::json!({
"type": "Pane Back Drop",
"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},
platform::MouseButton,
scene::MouseUp,
AppContext, Element, ElementBox, EventContext, MouseState, Quad, RenderContext, WeakViewHandle,
AppContext, Element, ElementBox, EventContext, MouseState, Quad, ViewContext, WeakViewHandle,
};
use project::ProjectEntryId;
use settings::Settings;
@ -22,14 +22,14 @@ pub fn dragged_item_receiver<Tag, F>(
drop_index: usize,
allow_same_pane: bool,
split_margin: Option<f32>,
cx: &mut RenderContext<Pane>,
cx: &mut ViewContext<Pane>,
render_child: F,
) -> MouseEventHandler<Tag>
where
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
// of if mouse position was accessed before
let drag_position = if state.hovered() {
@ -59,7 +59,7 @@ where
.unwrap_or(bounds);
cx.paint_stacking_context(None, None, |cx| {
cx.scene.push_quad(Quad {
scene.push_quad(Quad {
bounds: overlay_region,
background: Some(overlay_color(cx)),
border: Default::default(),
@ -102,7 +102,7 @@ pub fn handle_dropped_item(
index: usize,
allow_same_pane: bool,
split_margin: Option<f32>,
cx: &mut EventContext,
cx: &mut ViewContext<Self>,
) {
enum Action {
Move(WeakViewHandle<Pane>, usize),
@ -110,11 +110,11 @@ pub fn handle_dropped_item(
}
let drag_and_drop = cx.global::<DragAndDrop<Workspace>>();
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())
} 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)
} else {

View File

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

View File

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

View File

@ -1,7 +1,7 @@
use crate::StatusItemView;
use gpui::{
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 settings::Settings;
@ -188,7 +188,7 @@ impl View for 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() {
enum ResizeHandleTag {}
let style = &cx.global::<Settings>().theme.workspace.sidebar;
@ -225,7 +225,7 @@ impl View for SidebarButtons {
"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 tooltip_style = theme.tooltip.clone();
let theme = &theme.workspace.status_bar.sidebar_buttons;

View File

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

View File

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

View File

@ -45,8 +45,7 @@ use gpui::{
WindowOptions,
},
Action, AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Entity, ModelContext,
ModelHandle, RenderContext, SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle,
WeakViewHandle,
ModelHandle, SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
};
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
use language::LanguageRegistry;
@ -2054,10 +2053,10 @@ impl Workspace {
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
// (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 mut container_theme = theme.workspace.titlebar.container;
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() {
enum DisconnectedOverlay {}
Some(
@ -2810,7 +2809,7 @@ impl View for 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();
Stack::new()
.with_child(