making views in presenter.rs more composable
This commit is contained in:
parent
f98dc599f9
commit
e998d0778c
|
@ -31,6 +31,9 @@ use crate::{
|
||||||
BackgroundKind,
|
BackgroundKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const REFERENCE_WIDTH: f32 = 1920.0;
|
||||||
|
const REFERENCE_HEIGHT: f32 = 1080.0;
|
||||||
|
|
||||||
// #[derive(Default, Clone, Debug)]
|
// #[derive(Default, Clone, Debug)]
|
||||||
pub(crate) struct Presenter {
|
pub(crate) struct Presenter {
|
||||||
pub slides: Vec<Slide>,
|
pub slides: Vec<Slide>,
|
||||||
|
@ -363,159 +366,21 @@ impl Presenter {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view(&self) -> Element<Message> {
|
pub fn view(&self) -> Element<Message> {
|
||||||
responsive(|size| {
|
self.slide_view(
|
||||||
let font = self.current_font;
|
&self.current_slide,
|
||||||
let font_size = if self.current_slide.font_size() > 0 {
|
self.current_font,
|
||||||
(size.width / self.current_slide.font_size() as f32)
|
false,
|
||||||
* 3.0
|
true,
|
||||||
} else {
|
)
|
||||||
50.0
|
|
||||||
};
|
|
||||||
let slide_text = self.current_slide.text();
|
|
||||||
let lines = slide_text.lines();
|
|
||||||
let line_size = lines.clone().count();
|
|
||||||
// debug!(?lines);
|
|
||||||
let text: Vec<Element<Message>> = lines
|
|
||||||
.map(|t| {
|
|
||||||
text(t.to_string())
|
|
||||||
.size(font_size)
|
|
||||||
.font(font)
|
|
||||||
.width(Length::Fill)
|
|
||||||
.align_x(Horizontal::Center)
|
|
||||||
.into()
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let texts = Column::with_children(text);
|
|
||||||
// let text = text(self.current_slide.text())
|
|
||||||
// .size(font_size)
|
|
||||||
// .font(font)
|
|
||||||
// .align_x(Horizontal::Center);
|
|
||||||
let text = Container::new(texts).center(Length::Fill);
|
|
||||||
let text_background = Container::new(Space::new(0, 0))
|
|
||||||
.style(|_| {
|
|
||||||
container::background(
|
|
||||||
Background::Color(Color::BLACK)
|
|
||||||
.scale_alpha(0.3),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.width(size.width)
|
|
||||||
.height(
|
|
||||||
font_size * line_size as f32 * line_size as f32,
|
|
||||||
);
|
|
||||||
let text_stack = stack!(text_background, text);
|
|
||||||
let text_container =
|
|
||||||
Container::new(text_stack).center(Length::Fill);
|
|
||||||
let black = Container::new(Space::new(0, 0))
|
|
||||||
.style(|_| {
|
|
||||||
container::background(Background::Color(
|
|
||||||
Color::BLACK,
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.width(size.width)
|
|
||||||
.height(size.height);
|
|
||||||
let container = match self.current_slide.background().kind
|
|
||||||
{
|
|
||||||
BackgroundKind::Image => {
|
|
||||||
let path =
|
|
||||||
self.current_slide.background().path.clone();
|
|
||||||
Container::new(
|
|
||||||
image(path)
|
|
||||||
.content_fit(ContentFit::Cover)
|
|
||||||
.width(size.width)
|
|
||||||
.height(size.height),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
BackgroundKind::Video => {
|
|
||||||
if let Some(video) = &self.video {
|
|
||||||
Container::new(
|
|
||||||
VideoPlayer::new(video)
|
|
||||||
.mouse_hidden(true)
|
|
||||||
.width(size.width)
|
|
||||||
.height(size.width * 9.0 / 16.0)
|
|
||||||
.on_end_of_stream(Message::EndVideo)
|
|
||||||
.on_new_frame(Message::VideoFrame)
|
|
||||||
.on_missing_plugin(
|
|
||||||
Message::MissingPlugin,
|
|
||||||
)
|
|
||||||
.on_warning(|w| {
|
|
||||||
Message::Error(w.to_string())
|
|
||||||
})
|
|
||||||
.on_error(|e| {
|
|
||||||
Message::Error(e.to_string())
|
|
||||||
})
|
|
||||||
.content_fit(ContentFit::Cover),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Container::new(Space::new(0, 0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
stack!(
|
|
||||||
black,
|
|
||||||
container.center(Length::Fill),
|
|
||||||
text_container
|
|
||||||
)
|
|
||||||
.width(Length::Fill)
|
|
||||||
.height(Length::Fill)
|
|
||||||
.into()
|
|
||||||
})
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_preview(&self) -> Element<Message> {
|
pub fn view_preview(&self) -> Element<Message> {
|
||||||
responsive(|size| {
|
self.slide_view(
|
||||||
let font = self.current_font;
|
&self.current_slide,
|
||||||
let font_size = if self.current_slide.font_size() > 0 {
|
self.current_font,
|
||||||
(size.width / self.current_slide.font_size() as f32)
|
false,
|
||||||
* 3.0
|
false,
|
||||||
} else {
|
)
|
||||||
50.0
|
|
||||||
};
|
|
||||||
let text = text(self.current_slide.text())
|
|
||||||
.size(font_size)
|
|
||||||
.font(font);
|
|
||||||
let text = Container::new(text).center(Length::Fill);
|
|
||||||
let black = Container::new(Space::new(0, 0))
|
|
||||||
.style(|_| {
|
|
||||||
container::background(Background::Color(
|
|
||||||
Color::BLACK,
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.width(size.width)
|
|
||||||
.height(size.height);
|
|
||||||
let container = match self.current_slide.background().kind
|
|
||||||
{
|
|
||||||
BackgroundKind::Image => {
|
|
||||||
let path =
|
|
||||||
self.current_slide.background().path.clone();
|
|
||||||
Container::new(
|
|
||||||
image(path)
|
|
||||||
.content_fit(ContentFit::Cover)
|
|
||||||
.width(size.width)
|
|
||||||
.height(size.height),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
BackgroundKind::Video => {
|
|
||||||
if let Some(video) = &self.video {
|
|
||||||
Container::new(
|
|
||||||
VideoPlayer::new(video)
|
|
||||||
.width(size.width)
|
|
||||||
.height(size.width * 9.0 / 16.0)
|
|
||||||
.on_end_of_stream(Message::EndVideo)
|
|
||||||
.on_new_frame(Message::VideoFrame)
|
|
||||||
.content_fit(ContentFit::Cover),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Container::new(Space::new(0, 0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
stack!(black, container.center(Length::Fill), text)
|
|
||||||
.width(size.width)
|
|
||||||
.height(size.width * 9.0 / 16.0)
|
|
||||||
.into()
|
|
||||||
})
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn preview_bar(&self) -> Element<Message> {
|
pub fn preview_bar(&self) -> Element<Message> {
|
||||||
|
@ -547,86 +412,59 @@ impl Presenter {
|
||||||
stretch,
|
stretch,
|
||||||
style,
|
style,
|
||||||
};
|
};
|
||||||
|
|
||||||
let slide_id =
|
let slide_id =
|
||||||
self.slides.iter().position(|s| s == slide).unwrap()
|
self.slides.iter().position(|s| s == slide).unwrap()
|
||||||
as i32;
|
as i32;
|
||||||
let text = Responsive::new(move |size| {
|
|
||||||
let font_size = if slide.font_size() > 0 {
|
|
||||||
(size.width / slide.font_size() as f32) * 3.0
|
|
||||||
} else {
|
|
||||||
50.0
|
|
||||||
};
|
|
||||||
let text = text(slide.text()).size(font_size).font(font);
|
|
||||||
let text = Container::new(text).center(Length::Fill);
|
|
||||||
text.into()
|
|
||||||
});
|
|
||||||
let container = match slide.background().kind {
|
|
||||||
BackgroundKind::Image => {
|
|
||||||
let path = slide.background().path.clone();
|
|
||||||
|
|
||||||
Container::new(
|
let container = self.slide_view(slide, font, true, false);
|
||||||
image(path)
|
|
||||||
.content_fit(ContentFit::Contain)
|
|
||||||
.border_radius([10.0; 4]),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
BackgroundKind::Video => Container::new(Space::new(0, 0))
|
|
||||||
.style(|_| {
|
|
||||||
container::background(Background::Color(
|
|
||||||
Color::BLACK,
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.width(Length::Fill)
|
|
||||||
.height(Length::Fill),
|
|
||||||
};
|
|
||||||
let delegate = mouse_area(
|
let delegate = mouse_area(
|
||||||
Container::new(
|
Container::new(container)
|
||||||
stack!(container.center(Length::Fill), text)
|
.style(move |t| {
|
||||||
.width(Length::Fill)
|
let mut style = container::Style::default();
|
||||||
.height(Length::Fill),
|
let theme = t.cosmic();
|
||||||
)
|
let hovered = self.hovered_slide == slide_id;
|
||||||
.style(move |t| {
|
style.background = Some(Background::Color(
|
||||||
let mut style = container::Style::default();
|
|
||||||
let theme = t.cosmic();
|
|
||||||
let hovered = self.hovered_slide == slide_id;
|
|
||||||
style.background = Some(Background::Color(
|
|
||||||
if self.current_slide_index as i32 == slide_id {
|
|
||||||
theme.accent.base.into()
|
|
||||||
} else if hovered {
|
|
||||||
theme.accent.hover.into()
|
|
||||||
} else {
|
|
||||||
theme.palette.neutral_3.into()
|
|
||||||
},
|
|
||||||
));
|
|
||||||
style.border = Border::default().rounded(10.0);
|
|
||||||
style.shadow = Shadow {
|
|
||||||
color: Color::BLACK,
|
|
||||||
offset: {
|
|
||||||
if self.current_slide_index as i32 == slide_id
|
if self.current_slide_index as i32 == slide_id
|
||||||
{
|
{
|
||||||
Vector::new(5.0, 5.0)
|
theme.accent.base.into()
|
||||||
} else if hovered {
|
} else if hovered {
|
||||||
Vector::new(5.0, 5.0)
|
theme.accent.hover.into()
|
||||||
} else {
|
} else {
|
||||||
Vector::new(0.0, 0.0)
|
theme.palette.neutral_3.into()
|
||||||
}
|
},
|
||||||
},
|
));
|
||||||
blur_radius: {
|
style.border = Border::default().rounded(10.0);
|
||||||
if self.current_slide_index as i32 == slide_id
|
style.shadow = Shadow {
|
||||||
{
|
color: Color::BLACK,
|
||||||
10.0
|
offset: {
|
||||||
} else if hovered {
|
if self.current_slide_index as i32
|
||||||
10.0
|
== slide_id
|
||||||
} else {
|
{
|
||||||
0.0
|
Vector::new(5.0, 5.0)
|
||||||
}
|
} else if hovered {
|
||||||
},
|
Vector::new(5.0, 5.0)
|
||||||
};
|
} else {
|
||||||
style
|
Vector::new(0.0, 0.0)
|
||||||
})
|
}
|
||||||
.center_x(100.0 * 16.0 / 9.0)
|
},
|
||||||
.height(100)
|
blur_radius: {
|
||||||
.padding(10),
|
if self.current_slide_index as i32
|
||||||
|
== slide_id
|
||||||
|
{
|
||||||
|
10.0
|
||||||
|
} else if hovered {
|
||||||
|
10.0
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
style
|
||||||
|
})
|
||||||
|
.center_x(100.0 * 16.0 / 9.0)
|
||||||
|
.height(100)
|
||||||
|
.padding(10),
|
||||||
)
|
)
|
||||||
.interaction(cosmic::iced::mouse::Interaction::Pointer)
|
.interaction(cosmic::iced::mouse::Interaction::Pointer)
|
||||||
.on_enter(Message::HoveredSlide(slide_id))
|
.on_enter(Message::HoveredSlide(slide_id))
|
||||||
|
@ -639,6 +477,117 @@ impl Presenter {
|
||||||
delegate.into()
|
delegate.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn slide_view<'a>(
|
||||||
|
&'a self,
|
||||||
|
slide: &'a Slide,
|
||||||
|
font: Font,
|
||||||
|
delegate: bool,
|
||||||
|
hide_mouse: bool,
|
||||||
|
) -> Element<'a, Message> {
|
||||||
|
responsive(move |size| {
|
||||||
|
let font_size = scale_font(
|
||||||
|
slide.font_size() as f32,
|
||||||
|
size.width,
|
||||||
|
size.height,
|
||||||
|
);
|
||||||
|
let slide_text = slide.text();
|
||||||
|
let lines = slide_text.lines();
|
||||||
|
let line_size = lines.clone().count();
|
||||||
|
// debug!(?lines);
|
||||||
|
let text: Vec<Element<Message>> = lines
|
||||||
|
.map(|t| {
|
||||||
|
text(t.to_string())
|
||||||
|
.size(font_size)
|
||||||
|
.font(font)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.align_x(Horizontal::Center)
|
||||||
|
.into()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let texts = Column::with_children(text);
|
||||||
|
// let text = text(slide.text())
|
||||||
|
// .size(font_size)
|
||||||
|
// .font(font)
|
||||||
|
// .align_x(Horizontal::Center);
|
||||||
|
let text = Container::new(texts).center(Length::Fill);
|
||||||
|
let text_background = Container::new(Space::new(0, 0))
|
||||||
|
.style(|_| {
|
||||||
|
container::background(
|
||||||
|
Background::Color(Color::BLACK)
|
||||||
|
.scale_alpha(0.3),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.width(size.width)
|
||||||
|
.height(
|
||||||
|
font_size * line_size as f32 * line_size as f32,
|
||||||
|
);
|
||||||
|
let text_stack = stack!(text_background, text);
|
||||||
|
let text_container =
|
||||||
|
Container::new(text_stack).center(Length::Fill);
|
||||||
|
let black = Container::new(Space::new(0, 0))
|
||||||
|
.style(|_| {
|
||||||
|
container::background(Background::Color(
|
||||||
|
Color::BLACK,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.width(size.width)
|
||||||
|
.height(size.height);
|
||||||
|
let container = match slide.background().kind {
|
||||||
|
BackgroundKind::Image => {
|
||||||
|
let path = slide.background().path.clone();
|
||||||
|
Container::new(
|
||||||
|
image(path)
|
||||||
|
.content_fit(ContentFit::Cover)
|
||||||
|
.width(size.width)
|
||||||
|
.height(size.height),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
BackgroundKind::Video => {
|
||||||
|
if delegate {
|
||||||
|
Container::new(Space::new(0, 0))
|
||||||
|
.style(|_| {
|
||||||
|
container::background(
|
||||||
|
Background::Color(Color::BLACK),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(Length::Fill)
|
||||||
|
} else if let Some(video) = &self.video {
|
||||||
|
Container::new(
|
||||||
|
VideoPlayer::new(video)
|
||||||
|
.mouse_hidden(hide_mouse)
|
||||||
|
.width(size.width)
|
||||||
|
.height(size.width * 9.0 / 16.0)
|
||||||
|
.on_end_of_stream(Message::EndVideo)
|
||||||
|
.on_new_frame(Message::VideoFrame)
|
||||||
|
.on_missing_plugin(
|
||||||
|
Message::MissingPlugin,
|
||||||
|
)
|
||||||
|
.on_warning(|w| {
|
||||||
|
Message::Error(w.to_string())
|
||||||
|
})
|
||||||
|
.on_error(|e| {
|
||||||
|
Message::Error(e.to_string())
|
||||||
|
})
|
||||||
|
.content_fit(ContentFit::Cover),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Container::new(Space::new(0, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
stack!(
|
||||||
|
black,
|
||||||
|
container.center(Length::Fill),
|
||||||
|
text_container
|
||||||
|
)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(Length::Fill)
|
||||||
|
.into()
|
||||||
|
})
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
fn reset_video(&mut self) {
|
fn reset_video(&mut self) {
|
||||||
if let Some(slide) =
|
if let Some(slide) =
|
||||||
self.slides.get(self.current_slide_index as usize)
|
self.slides.get(self.current_slide_index as usize)
|
||||||
|
@ -681,3 +630,16 @@ async fn start_audio(sink: Arc<Sink>, audio: PathBuf) {
|
||||||
let paused = sink.is_paused();
|
let paused = sink.is_paused();
|
||||||
debug!(empty, paused, "Finished running");
|
debug!(empty, paused, "Finished running");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scale_font(font_size: f32, width: f32, height: f32) -> f32 {
|
||||||
|
let aspect_ratio_true = REFERENCE_WIDTH / REFERENCE_HEIGHT;
|
||||||
|
let aspect_ratio = width / height;
|
||||||
|
let scale_factor = (REFERENCE_WIDTH / width).sqrt();
|
||||||
|
// debug!(scale_factor);
|
||||||
|
let font_size = if font_size > 0.0 {
|
||||||
|
font_size / scale_factor
|
||||||
|
} else {
|
||||||
|
50.0
|
||||||
|
};
|
||||||
|
font_size
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue