Skip to content

Commit

Permalink
Create native Window view
Browse files Browse the repository at this point in the history
  • Loading branch information
matthunz committed Jan 9, 2024
1 parent 0d55cfd commit bebd6de
Show file tree
Hide file tree
Showing 9 changed files with 1,454 additions and 14 deletions.
1,336 changes: 1,331 additions & 5 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Expand Up @@ -14,12 +14,14 @@ members = [
]

[features]
native = ["winit"]
web = ["web-sys"]
full = ["web", "tracing"]
full = ["web", "tracing", "native"]

[dependencies]
rustc-hash = "1.1.0"
tracing = { version = "0.1.40", optional = true }
winit = { version = "0.29.9", optional = true }

[dependencies.web-sys]
version = "0.3.66"
Expand Down
20 changes: 20 additions & 0 deletions examples/window.rs
@@ -0,0 +1,20 @@
use viewbuilder::{
native::{self, Native, Window},
Model, View,
};

struct App;

impl Model<()> for App {
fn handle(&mut self, _msg: ()) -> viewbuilder::ControlFlow {
todo!()
}
}

fn app(_model: &App) -> impl View<Native<()>, ()> {
(Window::new(), Window::new())
}

fn main() {
native::run(App, app)
}
4 changes: 4 additions & 0 deletions src/lib.rs
Expand Up @@ -18,6 +18,10 @@ pub use self::rt::Runtime;
pub mod view;
pub use self::view::View;

#[cfg(feature = "native")]
#[cfg_attr(docsrs, doc(cfg(feature = "native")))]
pub mod native;

#[cfg(feature = "web")]
#[cfg_attr(docsrs, doc(cfg(feature = "web")))]
pub mod web;
Expand Down
88 changes: 88 additions & 0 deletions src/native/mod.rs
@@ -0,0 +1,88 @@
use crate::{Model, Runtime, View};
use std::{borrow::Cow, mem};
use winit::{
event_loop::{EventLoop, EventLoopBuilder, EventLoopWindowTarget},
window::{Window as RawWindow, WindowBuilder},
};

pub fn run<M, T, VB, V, E>(model: T, view_builder: VB)
where
T: Model<M>,
VB: FnMut(&T) -> V,
V: View<Native<E>, M>,
E: 'static,
M: Send + 'static,
{
let event_loop: EventLoop<E> = EventLoopBuilder::with_user_event().build().unwrap();
let state: Native<E> = Native { event_loop: None };
let mut rt = Runtime::new(|_msg| {}, model, view_builder, state);

event_loop
.run(|_, target| {
rt.state.event_loop = Some(unsafe { mem::transmute(target) });
if rt.element.is_none() {
rt.build();
} else {
rt.rebuild();
}
})
.unwrap();
}

pub struct Native<T: 'static> {
event_loop: Option<&'static EventLoopWindowTarget<T>>,
}

pub struct WindowData {
title: Cow<'static, str>,
}

pub struct Window {
data: Option<WindowData>,
}

impl Window {
pub fn new() -> Self {
Self {
data: Some(WindowData {
title: Cow::Borrowed("Viewbuilder"),
}),
}
}
}

impl<E, M> View<Native<E>, M> for Window {
type Element = (WindowData, RawWindow);

fn build(&mut self, _cx: &mut crate::Context<M>, state: &mut Native<E>) -> Self::Element {
let data = self.data.take().unwrap();
let window = WindowBuilder::new()
.with_title(data.title.clone())
.build(state.event_loop.as_ref().unwrap())
.unwrap();

(data, window)
}

fn rebuild(
&mut self,
_cx: &mut crate::Context<M>,
_state: &mut Native<E>,
element: &mut Self::Element,
) {
let data = self.data.take().unwrap();
if data.title != element.0.title {
element.0.title = data.title;
element.1.set_title(&element.0.title)
}
}

fn remove(
&mut self,
_cx: &mut crate::Context<M>,
_state: &mut Native<E>,
_element: Self::Element,
) {
todo!()
}
}
4 changes: 2 additions & 2 deletions src/rt.rs
Expand Up @@ -4,9 +4,9 @@ use crate::{Context, ControlFlow, Model, View};
pub struct Runtime<T, VB, E, M, S> {
model: T,
view_builder: VB,
element: Option<E>,
pub element: Option<E>,
cx: Context<M>,
state: S,
pub state: S,
}

impl<T, VB, E, M, S> Runtime<T, VB, E, M, S> {
Expand Down
8 changes: 4 additions & 4 deletions src/view/mod.rs
Expand Up @@ -316,9 +316,9 @@ where
fn rebuild(&mut self, cx: &mut Context<M>, state: &mut T, element: &mut Self::Element) {
let mut visited = Vec::new();
for (idx, (key, mut view)) in self.drain(..).enumerate() {
if let Some((key, last_view, element)) = element
if let Some((_key, _last_view, element)) = element
.iter_mut()
.find(|(view_key, view, element)| view_key == &key)
.find(|(view_key, _view, _element)| view_key == &key)
{
view.rebuild(cx, state, element)
} else {
Expand All @@ -329,7 +329,7 @@ where
}

let mut removes = Vec::new();
for (idx, (key, view, elem)) in element.iter_mut().enumerate() {
for (idx, (key, _view, _elem)) in element.iter_mut().enumerate() {
if !visited.contains(key) {
removes.push(idx);
}
Expand All @@ -340,7 +340,7 @@ where
}

fn remove(&mut self, cx: &mut Context<M>, state: &mut T, element: Self::Element) {
for (key, mut view, elem) in element {
for (_key, mut view, elem) in element {
view.remove(cx, state, elem);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/web/html.rs
Expand Up @@ -291,7 +291,7 @@ where
{
type Element = T;

fn build(&mut self, cx: &mut Context<M>, tree: &mut HtmlAttributes) -> Self::Element {
fn build(&mut self, _cx: &mut Context<M>, tree: &mut HtmlAttributes) -> Self::Element {
#[cfg(feature = "tracing")]
crate::build_span!("Class");

Expand Down
2 changes: 1 addition & 1 deletion src/web/mod.rs
@@ -1,5 +1,5 @@
use crate::{Context, ControlFlow, Model, Runtime, View};
use std::{borrow::Cow, cell::RefCell, rc::Rc, sync::Arc};
use std::{borrow::Cow, cell::RefCell, rc::Rc};
use web_sys::{wasm_bindgen::JsCast, Document, Element, Text};

pub mod html;
Expand Down

0 comments on commit bebd6de

Please sign in to comment.