Skip to content

Commit

Permalink
migrating to iced 0.13 (use the new stack widget instead of modal)
Browse files Browse the repository at this point in the history
  • Loading branch information
GyulyVGC committed Sep 20, 2024
1 parent 37d1cdf commit b308eb7
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 313 deletions.
8 changes: 4 additions & 4 deletions src/countries/country_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ fn get_flag_from_country(
flag
}
})))
.style(svg_style)
.class(svg_style)
.width(width)
.height(width * 0.75);

Expand Down Expand Up @@ -346,7 +346,7 @@ pub fn get_flag_tooltip(
Position::FollowCursor,
)
.snap_within_viewport(true)
.style(tooltip_style);
.class(tooltip_style);

if width == FLAGS_WIDTH_SMALL {
tooltip = tooltip.padding(3);
Expand All @@ -371,7 +371,7 @@ pub fn get_computer_tooltip(
(false, false, TrafficType::Unicast) => UNKNOWN,
},
)))
.style(SvgType::AdaptColor)
.class(SvgType::AdaptColor)
.width(FLAGS_WIDTH_BIG)
.height(FLAGS_WIDTH_BIG * 0.75);

Expand All @@ -390,5 +390,5 @@ pub fn get_computer_tooltip(
Position::FollowCursor,
)
.snap_within_viewport(true)
.style(ContainerType::Tooltip)
.class(ContainerType::Tooltip)
}
327 changes: 28 additions & 299 deletions src/gui/components/modal.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use iced::advanced::layout::{self, Layout};
use iced::advanced::overlay;
use iced::advanced::renderer;
use iced::advanced::widget::{self, Widget};
use iced::advanced::{self, Clipboard, Shell};
use iced::alignment::{Alignment, Horizontal, Vertical};
use iced::widget::{button, horizontal_space, Column, Container, Row, Space, Text};
use iced::{event, mouse, Color, Element, Event, Font, Length, Point, Rectangle, Size, Vector};
use iced::widget::{
button, center, container, horizontal_space, mouse_area, opaque, stack, Column, Container, Row,
Space, Text,
};
use iced::{Color, Element, Font, Length};

use crate::gui::components::button::button_hide;
use crate::gui::styles::button::ButtonType;
Expand Down Expand Up @@ -136,300 +134,31 @@ fn confirm_button_row(
)
}

/// A widget that centers an overlay element over some base element
pub struct Modal<'a, Message, Theme, Renderer> {
base: Element<'a, Message, Theme, Renderer>,
overlay: Element<'a, Message, Theme, Renderer>,
on_blur: Option<Message>,
}

impl<'a, Message, Theme, Renderer> Modal<'a, Message, Theme, Renderer> {
/// Returns a new [`Modal`]
pub fn new(
base: impl Into<Element<'a, Message, Theme, Renderer>>,
modal: impl Into<Element<'a, Message, Theme, Renderer>>,
) -> Self {
Self {
base: base.into(),
overlay: modal.into(),
on_blur: None,
}
}

/// Sets the message that will be produces when the background
/// of the [`Modal`] is pressed
pub fn on_blur(self, on_blur: Message) -> Self {
Self {
on_blur: Some(on_blur),
..self
}
}
}

impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
for Modal<'a, Message, Theme, Renderer>
where
Renderer: advanced::Renderer,
Message: Clone,
{
fn children(&self) -> Vec<widget::Tree> {
vec![
widget::Tree::new(&self.base),
widget::Tree::new(&self.overlay),
]
}

fn diff(&self, tree: &mut widget::Tree) {
tree.diff_children(&[&self.base, &self.overlay]);
}

fn size(&self) -> Size<Length> {
self.base.as_widget().size()
}

fn layout(
&self,
tree: &mut widget::Tree,
renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
self.base
.as_widget()
.layout(&mut tree.children[0], renderer, limits)
}

fn on_event(
&mut self,
state: &mut widget::Tree,
event: Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>,
viewport: &Rectangle,
) -> event::Status {
self.base.as_widget_mut().on_event(
&mut state.children[0],
event,
layout,
cursor,
renderer,
clipboard,
shell,
viewport,
)
}

fn draw(
&self,
state: &widget::Tree,
renderer: &mut Renderer,
theme: &Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor: mouse::Cursor,
viewport: &Rectangle,
) {
self.base.as_widget().draw(
&state.children[0],
renderer,
theme,
style,
layout,
cursor,
viewport,
);
}

fn overlay<'b>(
&'b mut self,
state: &'b mut widget::Tree,
layout: Layout<'_>,
_renderer: &Renderer,
translation: Vector,
) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
Some(overlay::Element::new(Box::new(Overlay {
position: layout.position() + translation,
content: &mut self.overlay,
tree: &mut state.children[1],
size: layout.bounds().size(),
on_blur: self.on_blur.clone(),
})))
}

fn mouse_interaction(
&self,
state: &widget::Tree,
layout: Layout<'_>,
cursor: mouse::Cursor,
viewport: &Rectangle,
renderer: &Renderer,
) -> mouse::Interaction {
self.base.as_widget().mouse_interaction(
&state.children[0],
layout,
cursor,
viewport,
renderer,
)
}

fn operate(
&self,
state: &mut widget::Tree,
layout: Layout<'_>,
renderer: &Renderer,
operation: &mut dyn widget::Operation<Message>,
) {
self.base
.as_widget()
.operate(&mut state.children[0], layout, renderer, operation);
}
}

struct Overlay<'a, 'b, Message, Theme, Renderer> {
position: Point,
content: &'b mut Element<'a, Message, Theme, Renderer>,
tree: &'b mut widget::Tree,
size: Size,
on_blur: Option<Message>,
}

impl<'a, 'b, Message, Theme, Renderer> overlay::Overlay<Message, Theme, Renderer>
for Overlay<'a, 'b, Message, Theme, Renderer>
pub fn new_modal<'a, Message, Theme, Renderer>(
base: impl Into<Element<'a, Message, Theme, Renderer>>,
content: impl Into<Element<'a, Message, Theme, Renderer>>,
on_blur: Message,
) -> Element<'a, Message, Theme, Renderer>
where
Renderer: advanced::Renderer,
Message: Clone,
Message: Clone + 'a,
{
fn layout(&mut self, renderer: &Renderer, _bounds: Size) -> layout::Node {
let limits = layout::Limits::new(Size::ZERO, self.size)
.width(Length::Fill)
.height(Length::Fill);

let child = self
.content
.as_widget()
.layout(self.tree, renderer, &limits)
.align(Alignment::Center, Alignment::Center, limits.max());

layout::Node::with_children(self.size, vec![child]).move_to(self.position)
}

fn on_event(
&mut self,
event: Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
renderer: &Renderer,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>,
) -> event::Status {
let content_bounds = layout.children().next().unwrap().bounds();

if let Some(message) = self.on_blur.as_ref() {
if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) = &event {
if !cursor.is_over(content_bounds) {
shell.publish(message.clone());
return event::Status::Captured;
stack![
base.into(),
opaque(
mouse_area(center(opaque(content)).style(|_theme| {
container::Style {
background: Some(
Color {
a: 0.8,
..Color::BLACK
}
.into(),
),
..container::Style::default()
}
}
}

self.content.as_widget_mut().on_event(
self.tree,
event,
layout.children().next().unwrap(),
cursor,
renderer,
clipboard,
shell,
&layout.bounds(),
}))
.on_press(on_blur)
)
}

fn draw(
&self,
renderer: &mut Renderer,
theme: &Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor: mouse::Cursor,
) {
renderer.fill_quad(
renderer::Quad {
bounds: layout.bounds(),
..renderer::Quad::default()
},
Color {
a: 0.80,
..Color::BLACK
},
);

self.content.as_widget().draw(
self.tree,
renderer,
theme,
style,
layout.children().next().unwrap(),
cursor,
&layout.bounds(),
);
}

fn operate(
&mut self,
layout: Layout<'_>,
renderer: &Renderer,
operation: &mut dyn widget::Operation<Message>,
) {
self.content.as_widget().operate(
self.tree,
layout.children().next().unwrap(),
renderer,
operation,
);
}

fn mouse_interaction(
&self,
layout: Layout<'_>,
cursor: mouse::Cursor,
viewport: &Rectangle,
renderer: &Renderer,
) -> mouse::Interaction {
self.content.as_widget().mouse_interaction(
self.tree,
layout.children().next().unwrap(),
cursor,
viewport,
renderer,
)
}

fn overlay<'c>(
&'c mut self,
layout: Layout<'_>,
renderer: &Renderer,
) -> Option<overlay::Element<'c, Message, Theme, Renderer>> {
self.content.as_widget_mut().overlay(
self.tree,
layout.children().next().unwrap(),
renderer,
Vector::ZERO,
)
}
}

impl<'a, Message, Theme, Renderer> From<Modal<'a, Message, Theme, Renderer>>
for Element<'a, Message, Theme, Renderer>
where
Theme: 'a,
Message: 'a + Clone,
Renderer: 'a + advanced::Renderer,
{
fn from(modal: Modal<'a, Message, Theme, Renderer>) -> Self {
Element::new(modal)
}
]
.into()
}
Loading

0 comments on commit b308eb7

Please sign in to comment.