Detailed changes
@@ -1177,7 +1177,7 @@ mod tests {
}
fn editor_blocks(editor: &ViewHandle<Editor>, cx: &mut AppContext) -> Vec<(u32, String)> {
- let mut presenter = cx.build_presenter(editor.id(), 0., Default::default());
+ let mut presenter = cx.build_window(editor.id(), 0., Default::default());
let mut cx = presenter.build_layout_context(Default::default(), false, cx);
cx.render(editor, |editor, cx| {
let snapshot = editor.snapshot(cx);
@@ -2531,7 +2531,7 @@ mod tests {
let layouts = editor.update(cx, |editor, cx| {
let snapshot = editor.snapshot(cx);
- let mut presenter = cx.build_presenter(window_id, 30., Default::default());
+ let mut presenter = cx.build_window(window_id, 30., Default::default());
let layout_cx = presenter.build_layout_context(Vector2F::zero(), false, cx);
element
.layout_line_numbers(0..6, &Default::default(), false, &snapshot, &layout_cx)
@@ -2568,7 +2568,7 @@ mod tests {
let mut element = EditorElement::new(editor.downgrade(), editor.read(cx).style(cx));
let mut scene = SceneBuilder::new(1.0);
- let mut presenter = cx.build_presenter(window_id, 30., Default::default());
+ let mut presenter = cx.build_window(window_id, 30., Default::default());
let mut layout_cx = presenter.build_layout_context(Vector2F::zero(), false, cx);
let (size, mut state) = element.layout(
SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)),
@@ -4,6 +4,7 @@ mod menu;
pub(crate) mod ref_counts;
#[cfg(any(test, feature = "test-support"))]
pub mod test_app_context;
+pub(crate) mod window;
mod window_input_handler;
use std::{
@@ -23,7 +24,6 @@ use std::{
use anyhow::{anyhow, Context, Result};
use parking_lot::Mutex;
-use pathfinder_geometry::vector::Vector2F;
use postage::oneshot;
use smallvec::SmallVec;
use smol::prelude::*;
@@ -48,8 +48,8 @@ use crate::{
self, Appearance, KeyDownEvent, KeyUpEvent, ModifiersChangedEvent, MouseButton,
PathPromptOptions, Platform, PromptLevel, WindowBounds, WindowOptions,
},
- presenter::Presenter,
util::post_inc,
+ window::{Window, WindowContext},
AssetCache, AssetSource, ClipboardItem, FontCache, MouseRegionId, TextLayoutCache,
};
@@ -1622,25 +1622,10 @@ impl AppContext {
let platform_window =
this.platform
.open_window(window_id, window_options, this.foreground.clone());
- let presenter = self.build_presenter(
- window_id,
- platform_window.titlebar_height(),
- platform_window.appearance(),
- );
- this.register_platform_window(window_id, &mut presenter, platform_window.as_mut());
+ let window =
+ this.build_window(window_id, root_view.clone().into_any(), platform_window);
- this.windows.insert(
- window_id,
- Window {
- root_view: root_view.clone().into_any(),
- focused_view_id: Some(root_view.id()),
- is_active: false,
- invalidation: None,
- is_fullscreen: false,
- platform_window,
- presenter,
- },
- );
+ this.windows.insert(window_id, window);
root_view.update(this, |view, cx| view.focus_in(cx.handle().into_any(), cx));
(window_id, root_view)
@@ -1658,27 +1643,11 @@ impl AppContext {
.build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx)))
.unwrap();
- let mut platform_window = this.platform.add_status_item();
- let mut presenter = self.build_presenter(
- window_id,
- platform_window.titlebar_height(),
- platform_window.appearance(),
- );
- this.register_platform_window(window_id, &mut presenter, platform_window.as_mut());
+ let platform_window = this.platform.add_status_item();
+ let window =
+ this.build_window(window_id, root_view.clone().into_any(), platform_window);
- let focused_view_id = root_view.id();
- this.windows.insert(
- window_id,
- Window {
- root_view: root_view.clone().into_any(),
- focused_view_id: Some(focused_view_id),
- is_active: false,
- invalidation: None,
- is_fullscreen: false,
- platform_window,
- presenter,
- },
- );
+ this.windows.insert(window_id, window);
root_view.update(this, |view, cx| view.focus_in(cx.handle().into_any(), cx));
(window_id, root_view)
@@ -1689,12 +1658,33 @@ impl AppContext {
self.remove_window(id);
}
- fn register_platform_window(
+ 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(
&mut self,
window_id: usize,
- presenter: &mut Presenter,
- platform_window: &mut dyn platform::Window,
- ) {
+ root_view: AnyViewHandle,
+ mut platform_window: Box<dyn platform::Window>,
+ ) -> Window {
{
let mut app = self.upgrade();
@@ -1758,51 +1748,19 @@ impl AppContext {
window_id,
}));
- let scene = presenter.build_scene(
- platform_window.content_size(),
- platform_window.scale_factor(),
- false,
- self,
- );
- platform_window.present_scene(scene);
- }
-
- 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_presenter(
- &mut self,
- window_id: usize,
- titlebar_height: f32,
- appearance: Appearance,
- ) -> Presenter {
- Presenter::new(
+ let mut window = Window::new(
window_id,
- titlebar_height,
- appearance,
+ root_view,
+ platform_window,
self.font_cache.clone(),
TextLayoutCache::new(self.platform.fonts()),
self.assets.clone(),
self,
- )
+ );
+
+ let scene = WindowContext::new(self, &mut window, window_id).build_scene(false);
+ window.platform_window.present_scene(scene);
+ window
}
pub fn add_view<T, F>(&mut self, parent_handle: &AnyViewHandle, build_view: F) -> ViewHandle<T>
@@ -2144,21 +2102,16 @@ impl AppContext {
}
fn update_windows(&mut self) {
- for (window_id, window) in &mut self.windows {
- if let Some(mut invalidation) = window.invalidation.take() {
- window.presenter.invalidate(
- &mut invalidation,
- window.platform_window.appearance(),
- self,
- );
- let scene = window.presenter.build_scene(
- window.platform_window.content_size(),
- window.platform_window.scale_factor(),
- false,
- self,
- );
- window.platform_window.present_scene(scene);
- }
+ let window_ids = self.windows.keys().cloned().collect::<Vec<_>>();
+ for window_id in window_ids {
+ self.update_window(window_id, |cx| {
+ if let Some(mut invalidation) = cx.window.invalidation.take() {
+ let appearance = cx.window.platform_window.appearance();
+ cx.invalidate(&mut invalidation, appearance);
+ let scene = cx.build_scene(false);
+ cx.window.platform_window.present_scene(scene);
+ }
+ });
}
}
@@ -2223,20 +2176,14 @@ impl AppContext {
}
fn perform_window_refresh(&mut self) {
- for window in self.windows.values_mut() {
- let mut invalidation = window.invalidation.take().unwrap_or_default();
- window.presenter.invalidate(
- &mut invalidation,
- window.platform_window.appearance(),
- self,
- );
- let scene = window.presenter.build_scene(
- window.platform_window.content_size(),
- window.platform_window.scale_factor(),
- true,
- self,
- );
- window.platform_window.present_scene(scene);
+ let window_ids = self.windows.keys().cloned().collect::<Vec<_>>();
+ for window_id in window_ids {
+ self.update_window(window_id, |cx| {
+ let mut invalidation = cx.window.invalidation.take().unwrap_or_default();
+ cx.invalidate(&mut invalidation, cx.window.platform_window.appearance());
+ let scene = cx.build_scene(true);
+ cx.window.platform_window.present_scene(scene);
+ });
}
}
@@ -2478,14 +2425,12 @@ impl AppContext {
self.update_window(window_id, |cx| {
if let Some(display) = cx.window_display_uuid() {
let bounds = cx.window_bounds();
- cx.window_bounds_observations.clone().emit(
- window_id,
- self,
- move |callback, this| {
+ cx.window_bounds_observations
+ .clone()
+ .emit(window_id, cx, move |callback, this| {
callback(bounds, display, this);
true
- },
- );
+ });
}
});
}
@@ -2708,16 +2653,6 @@ pub enum ParentId {
Root,
}
-pub struct Window {
- root_view: AnyViewHandle,
- focused_view_id: Option<usize>,
- is_active: bool,
- is_fullscreen: bool,
- invalidation: Option<WindowInvalidation>,
- presenter: Presenter,
- platform_window: Box<dyn platform::Window>,
-}
-
#[derive(Default, Clone)]
pub struct WindowInvalidation {
pub updated: HashSet<usize>,
@@ -3494,138 +3429,6 @@ impl<M> DerefMut for ModelContext<'_, M> {
}
}
-pub struct WindowContext<'a: 'b, 'b> {
- app_context: &'a mut AppContext,
- window: &'b mut Window,
- window_id: usize,
-}
-
-impl Deref for WindowContext<'_, '_> {
- type Target = AppContext;
-
- fn deref(&self) -> &Self::Target {
- self.app_context
- }
-}
-
-impl DerefMut for WindowContext<'_, '_> {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.app_context
- }
-}
-
-impl WindowContext<'_, '_> {
- pub fn dispatch_keystroke(&mut self, keystroke: &Keystroke) -> bool {
- let window_id = self.window_id;
- if let Some(focused_view_id) = self.focused_view_id(window_id) {
- let dispatch_path = self
- .ancestors(window_id, focused_view_id)
- .filter_map(|view_id| {
- self.views
- .get(&(window_id, view_id))
- .map(|view| (view_id, view.keymap_context(self)))
- })
- .collect();
-
- let match_result = self
- .keystroke_matcher
- .push_keystroke(keystroke.clone(), dispatch_path);
- let mut handled_by = None;
-
- let keystroke_handled = match &match_result {
- MatchResult::None => false,
- MatchResult::Pending => true,
- MatchResult::Matches(matches) => {
- for (view_id, action) in matches {
- if self.handle_dispatch_action_from_effect(
- window_id,
- Some(*view_id),
- action.as_ref(),
- ) {
- self.keystroke_matcher.clear_pending();
- handled_by = Some(action.boxed_clone());
- break;
- }
- }
- handled_by.is_some()
- }
- };
-
- self.keystroke(
- window_id,
- keystroke.clone(),
- handled_by,
- match_result.clone(),
- );
- keystroke_handled
- } else {
- self.keystroke(window_id, keystroke.clone(), None, MatchResult::None);
- false
- }
- }
-
- pub fn dispatch_event(&mut self, event: Event, event_reused: bool) -> bool {
- self.window
- .presenter
- .dispatch_event(event, event_reused, self)
- }
-
- pub fn set_window_title(&mut self, title: &str) {
- self.window.platform_window.set_title(title);
- }
-
- pub fn set_window_edited(&mut self, edited: bool) {
- self.window.platform_window.set_edited(edited);
- }
-
- pub fn is_topmost_window_for_position(&self, position: Vector2F) -> bool {
- self.window
- .platform_window
- .is_topmost_for_position(position)
- }
-
- pub fn activate_window(&self) {
- self.window.platform_window.activate();
- }
-
- pub fn window_bounds(&self) -> WindowBounds {
- self.window.platform_window.bounds()
- }
-
- pub fn window_display_uuid(&self) -> Option<Uuid> {
- self.window.platform_window.screen().display_uuid()
- }
-
- pub fn debug_elements(&self) -> Option<crate::json::Value> {
- self.window.presenter.debug_elements(self)
- }
-
- fn show_character_palette(&self) {
- self.window.platform_window.show_character_palette();
- }
-
- pub fn minimize_window(&self) {
- self.window.platform_window.minimize();
- }
-
- pub fn zoom_window(&self) {
- self.window.platform_window.zoom();
- }
-
- pub fn toggle_window_full_screen(&self) {
- self.window.platform_window.toggle_full_screen();
- }
-
- pub fn prompt(
- &self,
- level: PromptLevel,
- msg: &str,
- answers: &[&str],
- ) -> oneshot::Receiver<usize> {
- self.window.platform_window.prompt(level, msg, answers)
- }
-}
-
pub struct ViewContext<'a, T: ?Sized> {
app: &'a mut AppContext,
window_id: usize,
@@ -5139,6 +4942,7 @@ mod tests {
elements::*,
impl_actions,
platform::{MouseButton, MouseButtonEvent},
+ window::ChildView,
};
use itertools::Itertools;
use postage::{sink::Sink, stream::Stream};
@@ -6847,7 +6651,7 @@ mod tests {
let (window_id, root_view) = cx.add_window(Default::default(), |_| View(0));
cx.update_window(window_id, |cx| {
assert_eq!(
- cx.window.presenter.rendered_views[&root_view.id()].name(),
+ cx.window.rendered_views[&root_view.id()].name(),
Some("render count: 0")
);
});
@@ -6859,11 +6663,11 @@ mod tests {
cx.update_window(window_id, |cx| {
assert_eq!(
- cx.window.presenter.rendered_views[&root_view.id()].name(),
+ cx.window.rendered_views[&root_view.id()].name(),
Some("render count: 1")
);
assert_eq!(
- cx.window.presenter.rendered_views[&view.id()].name(),
+ cx.window.rendered_views[&view.id()].name(),
Some("render count: 0")
);
});
@@ -6872,11 +6676,11 @@ mod tests {
cx.update_window(window_id, |cx| {
assert_eq!(
- cx.window.presenter.rendered_views[&root_view.id()].name(),
+ cx.window.rendered_views[&root_view.id()].name(),
Some("render count: 2")
);
assert_eq!(
- cx.window.presenter.rendered_views[&view.id()].name(),
+ cx.window.rendered_views[&view.id()].name(),
Some("render count: 1")
);
});
@@ -6888,10 +6692,10 @@ mod tests {
cx.update_window(window_id, |cx| {
assert_eq!(
- cx.window.presenter.rendered_views[&root_view.id()].name(),
+ cx.window.rendered_views[&root_view.id()].name(),
Some("render count: 3")
);
- assert_eq!(cx.window.presenter.rendered_views.len(), 1);
+ assert_eq!(cx.window.rendered_views.len(), 1);
});
}
@@ -92,13 +92,12 @@ impl TestAppContext {
return true;
}
- if cx.window.presenter.dispatch_event(
+ if cx.dispatch_event(
Event::KeyDown(KeyDownEvent {
keystroke: keystroke.clone(),
is_held,
}),
false,
- cx,
) {
return true;
}
@@ -286,12 +285,15 @@ impl TestAppContext {
pub fn simulate_window_activation(&self, to_activate: Option<usize>) {
self.cx.borrow_mut().update(|cx| {
- for window_id in cx
+ let other_window_ids = cx
.windows
.keys()
.filter(|window_id| Some(**window_id) != to_activate)
- {
- cx.window_changed_active_status(*window_id, false)
+ .copied()
+ .collect::<Vec<_>>();
+
+ for window_id in other_window_ids {
+ cx.window_changed_active_status(window_id, false)
}
if let Some(to_activate) = to_activate {
@@ -4,7 +4,11 @@ use crate::{
font_cache::FontCache,
geometry::rect::RectF,
json::{self, ToJson},
- platform::{Appearance, CursorStyle, Event, FontSystem, MouseButton, MouseMovedEvent},
+ keymap_matcher::{Keystroke, MatchResult},
+ platform::{
+ self, Appearance, CursorStyle, Event, FontSystem, MouseButton, MouseMovedEvent,
+ PromptLevel, WindowBounds,
+ },
scene::{
CursorRegion, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseEvent, MouseHover,
MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene,
@@ -18,6 +22,7 @@ use crate::{
use anyhow::bail;
use collections::{HashMap, HashSet};
use pathfinder_geometry::vector::{vec2f, Vector2F};
+use postage::oneshot;
use serde_json::json;
use smallvec::SmallVec;
use sqlez::{
@@ -29,9 +34,16 @@ use std::{
ops::{Deref, DerefMut, Range},
sync::Arc,
};
+use uuid::Uuid;
-pub struct Presenter {
+pub struct Window {
window_id: usize,
+ pub(crate) root_view: AnyViewHandle,
+ pub(crate) focused_view_id: Option<usize>,
+ pub(crate) is_active: bool,
+ pub(crate) is_fullscreen: bool,
+ pub(crate) invalidation: Option<WindowInvalidation>,
+ pub(crate) platform_window: Box<dyn platform::Window>,
pub(crate) rendered_views: HashMap<usize, ElementBox>,
cursor_regions: Vec<CursorRegion>,
mouse_regions: Vec<(MouseRegion, usize)>,
@@ -47,18 +59,27 @@ pub struct Presenter {
appearance: Appearance,
}
-impl Presenter {
+impl Window {
pub fn new(
window_id: usize,
- titlebar_height: f32,
- appearance: Appearance,
+ root_view: AnyViewHandle,
+ platform_window: Box<dyn platform::Window>,
font_cache: Arc<FontCache>,
text_layout_cache: TextLayoutCache,
asset_cache: Arc<AssetCache>,
cx: &mut AppContext,
) -> Self {
+ let focused_view_id = Some(root_view.id());
+ let titlebar_height = platform_window.titlebar_height();
+ let appearance = platform_window.appearance();
Self {
window_id,
+ root_view,
+ focused_view_id,
+ is_active: false,
+ invalidation: None,
+ is_fullscreen: false,
+ platform_window,
rendered_views: cx.render_views(window_id, titlebar_height, appearance),
cursor_regions: Default::default(),
mouse_regions: Default::default(),
@@ -74,180 +95,101 @@ impl Presenter {
appearance,
}
}
+}
- pub fn invalidate(
- &mut self,
- invalidation: &mut WindowInvalidation,
- appearance: Appearance,
- cx: &mut AppContext,
- ) {
- cx.start_frame();
- self.appearance = appearance;
- for view_id in &invalidation.removed {
- invalidation.updated.remove(view_id);
- self.rendered_views.remove(view_id);
- }
- for view_id in &invalidation.updated {
- self.rendered_views.insert(
- *view_id,
- cx.render_view(RenderParams {
- window_id: self.window_id,
- view_id: *view_id,
- titlebar_height: self.titlebar_height,
- hovered_region_ids: self.hovered_region_ids.clone(),
- clicked_region_ids: self
- .clicked_button
- .map(|button| (self.clicked_region_ids.clone(), button)),
- refreshing: false,
- appearance,
- })
- .unwrap(),
- );
- }
- }
-
- pub fn refresh(
- &mut self,
- invalidation: &mut WindowInvalidation,
- appearance: Appearance,
- cx: &mut AppContext,
- ) {
- self.invalidate(invalidation, appearance, cx);
- for (view_id, view) in &mut self.rendered_views {
- if !invalidation.updated.contains(view_id) {
- *view = cx
- .render_view(RenderParams {
- window_id: self.window_id,
- view_id: *view_id,
- titlebar_height: self.titlebar_height,
- hovered_region_ids: self.hovered_region_ids.clone(),
- clicked_region_ids: self
- .clicked_button
- .map(|button| (self.clicked_region_ids.clone(), button)),
- refreshing: true,
- appearance,
- })
- .unwrap();
- }
- }
- }
-
- pub fn build_scene(
- &mut self,
- window_size: Vector2F,
- scale_factor: f32,
- refreshing: bool,
- cx: &mut AppContext,
- ) -> Scene {
- let mut scene_builder = SceneBuilder::new(scale_factor);
-
- if let Some(root_view_id) = cx.root_view_id(self.window_id) {
- self.layout(window_size, refreshing, cx);
- let mut paint_cx = self.build_paint_context(&mut scene_builder, window_size, cx);
- paint_cx.paint(
- root_view_id,
- Vector2F::zero(),
- RectF::new(Vector2F::zero(), window_size),
- );
- self.text_layout_cache.finish_frame();
- let scene = scene_builder.build();
- self.cursor_regions = scene.cursor_regions();
- self.mouse_regions = scene.mouse_regions();
-
- // window.is_topmost for the mouse moved event's postion?
- if cx.window_is_active(self.window_id) {
- if let Some(event) = self.last_mouse_moved_event.clone() {
- self.dispatch_event(event, true, cx);
- }
- }
+pub struct WindowContext<'a: 'b, 'b> {
+ app_context: &'a mut AppContext,
+ pub(crate) window: &'b mut Window, // TODO: make this private?
+ window_id: usize,
+}
- scene
- } else {
- log::error!("could not find root_view_id for window {}", self.window_id);
- scene_builder.build()
- }
- }
+impl Deref for WindowContext<'_, '_> {
+ type Target = AppContext;
- fn layout(&mut self, window_size: Vector2F, refreshing: bool, cx: &mut AppContext) {
- if let Some(root_view_id) = cx.root_view_id(self.window_id) {
- self.build_layout_context(window_size, refreshing, cx)
- .layout(root_view_id, SizeConstraint::strict(window_size));
- }
+ fn deref(&self) -> &Self::Target {
+ self.app_context
}
+}
- pub fn build_layout_context<'a>(
- &'a mut self,
- window_size: Vector2F,
- refreshing: bool,
- cx: &'a mut AppContext,
- ) -> LayoutContext<'a> {
- LayoutContext {
- window_id: self.window_id,
- rendered_views: &mut self.rendered_views,
- font_cache: &self.font_cache,
- font_system: cx.platform().fonts(),
- text_layout_cache: &self.text_layout_cache,
- asset_cache: &self.asset_cache,
- view_stack: Vec::new(),
- refreshing,
- hovered_region_ids: self.hovered_region_ids.clone(),
- clicked_region_ids: self
- .clicked_button
- .map(|button| (self.clicked_region_ids.clone(), button)),
- titlebar_height: self.titlebar_height,
- appearance: self.appearance,
- window_size,
- app: cx,
- }
+impl DerefMut for WindowContext<'_, '_> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.app_context
}
+}
- pub fn build_paint_context<'a>(
- &'a mut self,
- scene: &'a mut SceneBuilder,
- window_size: Vector2F,
- cx: &'a mut AppContext,
- ) -> PaintContext {
- PaintContext {
- scene,
- window_size,
- font_cache: &self.font_cache,
- text_layout_cache: &self.text_layout_cache,
- rendered_views: &mut self.rendered_views,
- view_stack: Vec::new(),
- app: cx,
+impl<'a: 'b, 'b> WindowContext<'a, 'b> {
+ pub fn new(app_context: &'a mut AppContext, window: &'b mut Window, window_id: usize) -> Self {
+ Self {
+ app_context,
+ window,
+ window_id,
}
}
- pub fn rect_for_text_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<RectF> {
- cx.focused_view_id(self.window_id).and_then(|view_id| {
- let cx = MeasurementContext {
- app: cx,
- rendered_views: &self.rendered_views,
- window_id: self.window_id,
+ pub fn dispatch_keystroke(&mut self, keystroke: &Keystroke) -> bool {
+ let window_id = self.window_id;
+ if let Some(focused_view_id) = self.focused_view_id(window_id) {
+ let dispatch_path = self
+ .ancestors(window_id, focused_view_id)
+ .filter_map(|view_id| {
+ self.views
+ .get(&(window_id, view_id))
+ .map(|view| (view_id, view.keymap_context(self)))
+ })
+ .collect();
+
+ let match_result = self
+ .keystroke_matcher
+ .push_keystroke(keystroke.clone(), dispatch_path);
+ let mut handled_by = None;
+
+ let keystroke_handled = match &match_result {
+ MatchResult::None => false,
+ MatchResult::Pending => true,
+ MatchResult::Matches(matches) => {
+ for (view_id, action) in matches {
+ if self.handle_dispatch_action_from_effect(
+ window_id,
+ Some(*view_id),
+ action.as_ref(),
+ ) {
+ self.keystroke_matcher.clear_pending();
+ handled_by = Some(action.boxed_clone());
+ break;
+ }
+ }
+ handled_by.is_some()
+ }
};
- cx.rect_for_text_range(view_id, range_utf16)
- })
+
+ self.keystroke(
+ window_id,
+ keystroke.clone(),
+ handled_by,
+ match_result.clone(),
+ );
+ keystroke_handled
+ } else {
+ self.keystroke(window_id, keystroke.clone(), None, MatchResult::None);
+ false
+ }
}
- pub fn dispatch_event(
- &mut self,
- event: Event,
- event_reused: bool,
- cx: &mut AppContext,
- ) -> bool {
+ pub fn dispatch_event(&mut self, event: Event, event_reused: bool) -> bool {
let mut mouse_events = SmallVec::<[_; 2]>::new();
let mut notified_views: HashSet<usize> = Default::default();
+ let window_id = self.window_id;
// 1. Handle platform event. Keyboard events get dispatched immediately, while mouse events
// get mapped into the mouse-specific MouseEvent type.
// -> These are usually small: [Mouse Down] or [Mouse up, Click] or [Mouse Moved, Mouse Dragged?]
// -> Also updates mouse-related state
match &event {
- Event::KeyDown(e) => return cx.dispatch_key_down(self.window_id, e),
+ Event::KeyDown(e) => return self.dispatch_key_down(window_id, e),
- Event::KeyUp(e) => return cx.dispatch_key_up(self.window_id, e),
+ Event::KeyUp(e) => return self.dispatch_key_up(window_id, e),
- Event::ModifiersChanged(e) => return cx.dispatch_modifiers_changed(self.window_id, e),
+ Event::ModifiersChanged(e) => return self.dispatch_modifiers_changed(window_id, e),
Event::MouseDown(e) => {
// Click events are weird because they can be fired after a drag event.
@@ -256,8 +198,9 @@ impl Presenter {
// So we need to store the overlapping regions on mouse down.
// If there is already clicked_button stored, don't replace it.
- if self.clicked_button.is_none() {
- self.clicked_region_ids = self
+ if self.window.clicked_button.is_none() {
+ self.window.clicked_region_ids = self
+ .window
.mouse_regions
.iter()
.filter_map(|(region, _)| {
@@ -269,7 +212,7 @@ impl Presenter {
})
.collect();
- self.clicked_button = Some(e.button);
+ self.window.clicked_button = Some(e.button);
}
mouse_events.push(MouseEvent::Down(MouseDown {
@@ -308,26 +251,29 @@ impl Presenter {
},
) => {
let mut style_to_assign = CursorStyle::Arrow;
- for region in self.cursor_regions.iter().rev() {
+ for region in self.window.cursor_regions.iter().rev() {
if region.bounds.contains_point(*position) {
style_to_assign = region.style;
break;
}
}
- // TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- // if cx.is_topmost_window_for_position(self.window_id, *position) {
- // cx.platform().set_cursor_style(style_to_assign);
- // }
+ if self
+ .window
+ .platform_window
+ .is_topmost_for_position(*position)
+ {
+ self.platform().set_cursor_style(style_to_assign);
+ }
if !event_reused {
if pressed_button.is_some() {
mouse_events.push(MouseEvent::Drag(MouseDrag {
region: Default::default(),
- prev_mouse_position: self.mouse_position,
+ prev_mouse_position: self.window.mouse_position,
platform_event: e.clone(),
}));
- } else if let Some(clicked_button) = self.clicked_button {
+ } else if let Some(clicked_button) = self.window.clicked_button {
// Mouse up event happened outside the current window. Simulate mouse up button event
let button_event = e.to_button_event(clicked_button);
mouse_events.push(MouseEvent::Up(MouseUp {
@@ -359,7 +305,7 @@ impl Presenter {
region: Default::default(),
}));
- self.last_mouse_moved_event = Some(event.clone());
+ self.window.last_mouse_moved_event = Some(event.clone());
}
Event::MouseExited(event) => {
@@ -373,7 +319,6 @@ impl Presenter {
modifiers: event.modifiers,
}),
event_reused,
- cx,
);
}
@@ -384,7 +329,7 @@ impl Presenter {
}
if let Some(position) = event.position() {
- self.mouse_position = position;
+ self.window.mouse_position = position;
}
// 2. Dispatch mouse events on regions
@@ -398,8 +343,8 @@ impl Presenter {
match &mouse_event {
MouseEvent::Hover(_) => {
let mut highest_z_index = None;
- let mouse_position = self.mouse_position.clone();
- for (region, z_index) in self.mouse_regions.iter().rev() {
+ let mouse_position = self.window.mouse_position.clone();
+ for (region, z_index) in self.window.mouse_regions.iter().rev() {
// Allow mouse regions to appear transparent to hovers
if !region.hoverable {
continue;
@@ -417,7 +362,7 @@ impl Presenter {
// highest_z_index is set.
if contains_mouse && z_index == highest_z_index.unwrap() {
//Ensure that hover entrance events aren't sent twice
- if self.hovered_region_ids.insert(region.id()) {
+ if self.window.hovered_region_ids.insert(region.id()) {
valid_regions.push(region.clone());
if region.notify_on_hover {
notified_views.insert(region.id().view_id());
@@ -425,7 +370,7 @@ impl Presenter {
}
} else {
// Ensure that hover exit events aren't sent twice
- if self.hovered_region_ids.remove(®ion.id()) {
+ if self.window.hovered_region_ids.remove(®ion.id()) {
valid_regions.push(region.clone());
if region.notify_on_hover {
notified_views.insert(region.id().view_id());
@@ -436,8 +381,8 @@ impl Presenter {
}
MouseEvent::Down(_) | MouseEvent::Up(_) => {
- for (region, _) in self.mouse_regions.iter().rev() {
- if region.bounds.contains_point(self.mouse_position) {
+ for (region, _) in self.window.mouse_regions.iter().rev() {
+ if region.bounds.contains_point(self.window.mouse_position) {
valid_regions.push(region.clone());
if region.notify_on_click {
notified_views.insert(region.id().view_id());
@@ -449,19 +394,25 @@ impl Presenter {
MouseEvent::Click(e) => {
// Only raise click events if the released button is the same as the one stored
if self
+ .window
.clicked_button
.map(|clicked_button| clicked_button == e.button)
.unwrap_or(false)
{
// Clear clicked regions and clicked button
- let clicked_region_ids =
- std::mem::replace(&mut self.clicked_region_ids, Default::default());
- self.clicked_button = None;
+ let clicked_region_ids = std::mem::replace(
+ &mut self.window.clicked_region_ids,
+ Default::default(),
+ );
+ self.window.clicked_button = None;
// Find regions which still overlap with the mouse since the last MouseDown happened
- for (mouse_region, _) in self.mouse_regions.iter().rev() {
+ for (mouse_region, _) in self.window.mouse_regions.iter().rev() {
if clicked_region_ids.contains(&mouse_region.id()) {
- if mouse_region.bounds.contains_point(self.mouse_position) {
+ if mouse_region
+ .bounds
+ .contains_point(self.window.mouse_position)
+ {
valid_regions.push(mouse_region.clone());
}
}
@@ -470,26 +421,32 @@ impl Presenter {
}
MouseEvent::Drag(_) => {
- for (mouse_region, _) in self.mouse_regions.iter().rev() {
- if self.clicked_region_ids.contains(&mouse_region.id()) {
+ for (mouse_region, _) in self.window.mouse_regions.iter().rev() {
+ if self.window.clicked_region_ids.contains(&mouse_region.id()) {
valid_regions.push(mouse_region.clone());
}
}
}
MouseEvent::MoveOut(_) | MouseEvent::UpOut(_) | MouseEvent::DownOut(_) => {
- for (mouse_region, _) in self.mouse_regions.iter().rev() {
+ for (mouse_region, _) in self.window.mouse_regions.iter().rev() {
// NOT contains
- if !mouse_region.bounds.contains_point(self.mouse_position) {
+ if !mouse_region
+ .bounds
+ .contains_point(self.window.mouse_position)
+ {
valid_regions.push(mouse_region.clone());
}
}
}
_ => {
- for (mouse_region, _) in self.mouse_regions.iter().rev() {
+ for (mouse_region, _) in self.window.mouse_regions.iter().rev() {
// Contains
- if mouse_region.bounds.contains_point(self.mouse_position) {
+ if mouse_region
+ .bounds
+ .contains_point(self.window.mouse_position)
+ {
valid_regions.push(mouse_region.clone());
}
}
@@ -497,9 +454,9 @@ impl Presenter {
}
//3. Fire region events
- let hovered_region_ids = self.hovered_region_ids.clone();
+ 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, cx);
+ let mut event_cx = self.build_event_context(&mut notified_views);
mouse_event.set_region(valid_region.bounds);
if let MouseEvent::Hover(e) = &mut mouse_event {
@@ -548,43 +505,253 @@ impl Presenter {
}
for view_id in notified_views {
- cx.notify_view(self.window_id, view_id);
+ self.notify_view(window_id, view_id);
}
any_event_handled
}
- pub fn build_event_context<'a>(
- &'a mut self,
- notified_views: &'a mut HashSet<usize>,
- cx: &'a mut AppContext,
- ) -> EventContext<'a> {
+ pub fn build_event_context<'c>(
+ &'c mut self,
+ notified_views: &'c mut HashSet<usize>,
+ ) -> EventContext<'c> {
EventContext {
- font_cache: &self.font_cache,
- text_layout_cache: &self.text_layout_cache,
+ font_cache: &self.window.font_cache,
+ text_layout_cache: &self.window.text_layout_cache,
view_stack: Default::default(),
notified_views,
notify_count: 0,
handled: false,
window_id: self.window_id,
+ app: self,
+ }
+ }
+
+ pub fn invalidate(&mut self, invalidation: &mut WindowInvalidation, appearance: Appearance) {
+ self.start_frame();
+ self.window.appearance = appearance;
+ for view_id in &invalidation.removed {
+ invalidation.updated.remove(view_id);
+ self.window.rendered_views.remove(view_id);
+ }
+ for view_id in &invalidation.updated {
+ let window_id = self.window_id;
+ let titlebar_height = self.window.titlebar_height;
+ let hovered_region_ids = self.window.hovered_region_ids.clone();
+ let clicked_region_ids = self
+ .window
+ .clicked_button
+ .map(|button| (self.window.clicked_region_ids.clone(), button));
+
+ let element = self
+ .render_view(RenderParams {
+ window_id,
+ view_id: *view_id,
+ titlebar_height,
+ hovered_region_ids,
+ clicked_region_ids,
+ refreshing: false,
+ appearance,
+ })
+ .unwrap();
+ self.window.rendered_views.insert(*view_id, element);
+ }
+ }
+
+ pub fn refresh(&mut self, invalidation: &mut WindowInvalidation, appearance: Appearance) {
+ self.invalidate(invalidation, appearance);
+
+ let view_ids = self
+ .window
+ .rendered_views
+ .keys()
+ .copied()
+ .collect::<Vec<_>>();
+
+ for view_id in view_ids {
+ if !invalidation.updated.contains(&view_id) {
+ let window_id = self.window_id;
+ let titlebar_height = self.window.titlebar_height;
+ let hovered_region_ids = self.window.hovered_region_ids.clone();
+ let clicked_region_ids = self
+ .window
+ .clicked_button
+ .map(|button| (self.window.clicked_region_ids.clone(), button));
+ let element = self
+ .render_view(RenderParams {
+ window_id,
+ view_id,
+ titlebar_height,
+ hovered_region_ids,
+ clicked_region_ids,
+ refreshing: true,
+ appearance,
+ })
+ .unwrap();
+ self.window.rendered_views.insert(view_id, element);
+ }
+ }
+ }
+
+ pub fn build_scene(&mut self, refreshing: bool) -> Scene {
+ let window_size = self.window.platform_window.content_size();
+ let scale_factor = self.window.platform_window.scale_factor();
+
+ let mut scene_builder = SceneBuilder::new(scale_factor);
+
+ if let Some(root_view_id) = self.root_view_id(self.window_id) {
+ self.layout(window_size, refreshing, self);
+ let mut paint_cx = self.build_paint_context(&mut scene_builder, window_size);
+ paint_cx.paint(
+ root_view_id,
+ Vector2F::zero(),
+ RectF::new(Vector2F::zero(), window_size),
+ );
+ self.window.text_layout_cache.finish_frame();
+ let scene = scene_builder.build();
+ self.window.cursor_regions = scene.cursor_regions();
+ self.window.mouse_regions = scene.mouse_regions();
+
+ // window.is_topmost for the mouse moved event's postion?
+ if self.window_is_active(self.window_id) {
+ if let Some(event) = self.window.last_mouse_moved_event.clone() {
+ self.dispatch_event(event, true);
+ }
+ }
+
+ scene
+ } else {
+ log::error!("could not find root_view_id for window {}", self.window_id);
+ scene_builder.build()
+ }
+ }
+
+ fn layout(&mut self, window_size: Vector2F, refreshing: bool, cx: &mut AppContext) {
+ if let Some(root_view_id) = cx.root_view_id(self.window_id) {
+ self.build_layout_context(window_size, refreshing, cx)
+ .layout(root_view_id, SizeConstraint::strict(window_size));
+ }
+ }
+
+ pub fn build_layout_context<'c>(
+ &'c mut self,
+ window_size: Vector2F,
+ refreshing: bool,
+ cx: &'c mut AppContext,
+ ) -> LayoutContext<'c> {
+ LayoutContext {
+ window_id: self.window_id,
+ rendered_views: &mut self.window.rendered_views,
+ font_cache: &self.font_cache,
+ font_system: cx.platform().fonts(),
+ text_layout_cache: &self.window.text_layout_cache,
+ asset_cache: &self.window.asset_cache,
+ view_stack: Vec::new(),
+ refreshing,
+ hovered_region_ids: self.window.hovered_region_ids.clone(),
+ clicked_region_ids: self
+ .window
+ .clicked_button
+ .map(|button| (self.window.clicked_region_ids.clone(), button)),
+ titlebar_height: self.window.titlebar_height,
+ appearance: self.window.appearance,
+ window_size,
app: cx,
}
}
- pub fn debug_elements(&self, cx: &AppContext) -> Option<json::Value> {
- let view = cx.root_view(self.window_id)?;
+ pub fn build_paint_context<'c>(
+ &'c mut self,
+ scene: &'c mut SceneBuilder,
+ window_size: Vector2F,
+ ) -> PaintContext {
+ PaintContext {
+ scene,
+ window_size,
+ font_cache: &self.font_cache,
+ text_layout_cache: &self.window.text_layout_cache,
+ rendered_views: &mut self.window.rendered_views,
+ view_stack: Vec::new(),
+ app: self,
+ }
+ }
+
+ pub fn rect_for_text_range(&self, range_utf16: Range<usize>) -> Option<RectF> {
+ self.focused_view_id(self.window_id).and_then(|view_id| {
+ let cx = MeasurementContext {
+ app: self,
+ rendered_views: &self.window.rendered_views,
+ window_id: self.window_id,
+ };
+ cx.rect_for_text_range(view_id, range_utf16)
+ })
+ }
+
+ pub fn debug_elements(&self) -> Option<json::Value> {
+ let view = self.root_view(self.window_id)?;
Some(json!({
- "root_view": view.debug_json(cx),
- "root_element": self.rendered_views.get(&view.id())
+ "root_view": view.debug_json(self),
+ "root_element": self.window.rendered_views.get(&view.id())
.map(|root_element| {
root_element.debug(&DebugContext {
- rendered_views: &self.rendered_views,
- font_cache: &self.font_cache,
- app: cx,
+ rendered_views: &self.window.rendered_views,
+ font_cache: &self.window.font_cache,
+ app: self,
})
})
}))
}
+
+ pub fn set_window_title(&mut self, title: &str) {
+ self.window.platform_window.set_title(title);
+ }
+
+ pub fn set_window_edited(&mut self, edited: bool) {
+ self.window.platform_window.set_edited(edited);
+ }
+
+ pub fn is_topmost_window_for_position(&self, position: Vector2F) -> bool {
+ self.window
+ .platform_window
+ .is_topmost_for_position(position)
+ }
+
+ pub fn activate_window(&self) {
+ self.window.platform_window.activate();
+ }
+
+ pub fn window_bounds(&self) -> WindowBounds {
+ self.window.platform_window.bounds()
+ }
+
+ pub fn window_display_uuid(&self) -> Option<Uuid> {
+ self.window.platform_window.screen().display_uuid()
+ }
+
+ fn show_character_palette(&self) {
+ self.window.platform_window.show_character_palette();
+ }
+
+ pub fn minimize_window(&self) {
+ self.window.platform_window.minimize();
+ }
+
+ pub fn zoom_window(&self) {
+ self.window.platform_window.zoom();
+ }
+
+ pub fn toggle_window_full_screen(&self) {
+ self.window.platform_window.toggle_full_screen();
+ }
+
+ pub fn prompt(
+ &self,
+ level: PromptLevel,
+ msg: &str,
+ answers: &[&str],
+ ) -> oneshot::Receiver<usize> {
+ self.window.platform_window.prompt(level, msg, answers)
+ }
}
pub struct LayoutContext<'a> {
@@ -90,8 +90,9 @@ impl InputHandler for WindowInputHandler {
}
fn rect_for_range(&self, range_utf16: Range<usize>) -> Option<RectF> {
- let app = self.app.borrow();
- let window = app.windows.get(&self.window_id)?;
- window.presenter.rect_for_text_range(range_utf16, &app)
+ self.app
+ .borrow_mut()
+ .update_window(self.window_id, |cx| cx.rect_for_text_range(range_utf16))
+ .flatten()
}
}
@@ -26,16 +26,14 @@ pub use self::{
stack::*, svg::*, text::*, tooltip::*, uniform_list::*,
};
use self::{clipped::Clipped, expanded::Expanded};
-pub use crate::presenter::ChildView;
use crate::{
+ app::window::MeasurementContext,
geometry::{
rect::RectF,
vector::{vec2f, Vector2F},
},
- json,
- presenter::MeasurementContext,
- Action, DebugContext, EventContext, LayoutContext, PaintContext, RenderContext, SizeConstraint,
- View,
+ json, Action, DebugContext, EventContext, LayoutContext, PaintContext, RenderContext,
+ SizeConstraint, View,
};
use core::panic;
use json::ToJson;
@@ -1,7 +1,7 @@
use crate::{
geometry::{rect::RectF, vector::Vector2F},
json,
- presenter::MeasurementContext,
+ window::MeasurementContext,
DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
use json::ToJson;
@@ -1,7 +1,7 @@
use super::Element;
use crate::{
json::{self, json},
- presenter::MeasurementContext,
+ window::MeasurementContext,
DebugContext, PaintContext,
};
use json::ToJson;
@@ -6,7 +6,7 @@ use serde_json::json;
use crate::{
geometry::{rect::RectF, vector::Vector2F},
json,
- presenter::MeasurementContext,
+ window::MeasurementContext,
DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
@@ -9,8 +9,8 @@ use crate::{
},
json::ToJson,
platform::CursorStyle,
- presenter::MeasurementContext,
scene::{self, Border, CursorRegion, Quad},
+ window::MeasurementContext,
Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
use serde::Deserialize;
@@ -6,7 +6,7 @@ use crate::{
vector::{vec2f, Vector2F},
},
json::{json, ToJson},
- presenter::MeasurementContext,
+ window::MeasurementContext,
DebugContext,
};
use crate::{Element, LayoutContext, PaintContext, SizeConstraint};
@@ -3,7 +3,7 @@ use std::ops::Range;
use crate::{
geometry::{rect::RectF, vector::Vector2F},
json,
- presenter::MeasurementContext,
+ window::MeasurementContext,
DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
use serde_json::json;
@@ -2,7 +2,7 @@ use std::{any::Any, cell::Cell, f32::INFINITY, ops::Range, rc::Rc};
use crate::{
json::{self, ToJson, Value},
- presenter::MeasurementContext,
+ window::MeasurementContext,
Axis, DebugContext, Element, ElementBox, ElementStateHandle, LayoutContext, PaintContext,
RenderContext, SizeConstraint, Vector2FExt, View,
};
@@ -3,7 +3,7 @@ use std::ops::Range;
use crate::{
geometry::{rect::RectF, vector::Vector2F},
json::json,
- presenter::MeasurementContext,
+ window::MeasurementContext,
DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
@@ -5,8 +5,9 @@ use crate::{
vector::{vec2f, Vector2F},
},
json::{json, ToJson},
- presenter::MeasurementContext,
- scene, Border, DebugContext, Element, ImageData, LayoutContext, PaintContext, SizeConstraint,
+ scene,
+ window::MeasurementContext,
+ Border, DebugContext, Element, ImageData, LayoutContext, PaintContext, SizeConstraint,
};
use serde::Deserialize;
use std::{ops::Range, sync::Arc};
@@ -7,8 +7,8 @@ use crate::{
vector::{vec2f, Vector2F},
},
json::{ToJson, Value},
- presenter::MeasurementContext,
text_layout::{Line, RunStyle},
+ window::MeasurementContext,
DebugContext, Element, LayoutContext, PaintContext, SizeConstraint,
};
use serde::Deserialize;
@@ -4,7 +4,7 @@ use crate::{
vector::{vec2f, Vector2F},
},
json::json,
- presenter::MeasurementContext,
+ window::MeasurementContext,
DebugContext, Element, ElementBox, ElementRc, EventContext, LayoutContext, MouseRegion,
PaintContext, RenderContext, SizeConstraint, View, ViewContext,
};
@@ -631,7 +631,6 @@ mod tests {
#[crate::test(self)]
fn test_layout(cx: &mut crate::AppContext) {
- let mut presenter = cx.build_presenter(0, 0., Default::default());
let (_, view) = cx.add_window(Default::default(), |_| TestView);
let constraint = SizeConstraint::new(vec2f(0., 0.), vec2f(100., 40.));
@@ -730,8 +729,7 @@ mod tests {
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
.unwrap_or(10);
- let (_, view) = cx.add_window(Default::default(), |_| TestView);
- let mut presenter = cx.build_presenter(0, 0., Default::default());
+ let (window_id, view) = cx.add_window(Default::default(), |_| TestView);
let mut next_id = 0;
let elements = Rc::new(RefCell::new(
(0..rng.gen_range(0..=20))
@@ -3,7 +3,7 @@ use std::ops::Range;
use crate::{
geometry::{rect::RectF, vector::Vector2F},
json::ToJson,
- presenter::MeasurementContext,
+ window::MeasurementContext,
Axis, DebugContext, Element, ElementBox, LayoutContext, MouseRegion, PaintContext,
SizeConstraint,
};
@@ -3,7 +3,7 @@ use std::ops::Range;
use crate::{
geometry::{rect::RectF, vector::Vector2F},
json::{self, json, ToJson},
- presenter::MeasurementContext,
+ window::MeasurementContext,
DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
@@ -8,8 +8,9 @@ use crate::{
rect::RectF,
vector::{vec2f, Vector2F},
},
- presenter::MeasurementContext,
- scene, DebugContext, Element, LayoutContext, PaintContext, SizeConstraint,
+ scene,
+ window::MeasurementContext,
+ DebugContext, Element, LayoutContext, PaintContext, SizeConstraint,
};
pub struct Svg {
@@ -6,8 +6,8 @@ use crate::{
vector::{vec2f, Vector2F},
},
json::{ToJson, Value},
- presenter::MeasurementContext,
text_layout::{Line, RunStyle, ShapedBoundary},
+ window::MeasurementContext,
DebugContext, Element, FontCache, LayoutContext, PaintContext, SizeConstraint, TextLayoutCache,
};
use log::warn;
@@ -271,12 +271,18 @@ pub fn layout_highlighted_chunks<'a>(
#[cfg(test)]
mod tests {
use super::*;
- use crate::{elements::Empty, fonts, AppContext, ElementBox, Entity, RenderContext, View};
+ use crate::{
+ elements::Empty, fonts, platform, AppContext, ElementBox, Entity, RenderContext, View,
+ };
#[crate::test(self)]
fn test_soft_wrapping_with_carriage_returns(cx: &mut AppContext) {
- let (window_id, _) = cx.add_window(Default::default(), |_| TestView);
- let mut presenter = cx.build_presenter(window_id, Default::default(), Default::default());
+ 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(
@@ -6,7 +6,7 @@ use crate::{
fonts::TextStyle,
geometry::{rect::RectF, vector::Vector2F},
json::json,
- presenter::MeasurementContext,
+ window::MeasurementContext,
Action, Axis, ElementStateHandle, LayoutContext, PaintContext, RenderContext, SizeConstraint,
Task, View,
};
@@ -6,8 +6,8 @@ use crate::{
},
json::{self, json},
platform::ScrollWheelEvent,
- presenter::MeasurementContext,
scene::MouseScrollWheel,
+ window::MeasurementContext,
ElementBox, MouseRegion, RenderContext, View,
};
use json::ToJson;
@@ -14,7 +14,6 @@ mod clipboard;
pub use clipboard::ClipboardItem;
pub mod fonts;
pub mod geometry;
-mod presenter;
pub mod scene;
pub use scene::{Border, CursorRegion, MouseRegion, MouseRegionId, Quad, Scene, SceneBuilder};
pub mod text_layout;
@@ -28,7 +27,7 @@ pub mod json;
pub mod keymap_matcher;
pub mod platform;
pub use gpui_macros::test;
-pub use presenter::{
+pub use window::{
Axis, DebugContext, EventContext, LayoutContext, MeasurementContext, PaintContext,
SizeConstraint, Vector2FExt,
};
@@ -261,7 +261,7 @@ pub struct Window {
}
impl Window {
- fn new(size: Vector2F) -> Self {
+ pub fn new(size: Vector2F) -> Self {
Self {
size,
event_handlers: Default::default(),