[Rust] iced: ๋ ˆ์ด์•„์›ƒ - Stack

0.13 ๋ฒ„์ „ ๊ธฐ์ค€์ด๋‹ค.



Stack ์ปดํฌ๋„ŒํŠธ

Stack ์ปดํฌ๋„ŒํŠธ๋Š” ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์Œ“์•„์˜ฌ๋ฆฌ๋Š” ์—ญํ• ์„ ํ•˜๋Š” ์œ„์ ฏ์ด๋‹ค.
์š”์†Œ ์ˆœ์„œ๋Œ€๋กœ ์ธต์ธต์ด ์Œ“์•„์˜ฌ๋ฆฐ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์ด ์ฝ”๋“œ๋Š” ๋ฐฐ๊ฒฝ์— ๋จผ์ € ๋นจ๊ฐ„์ƒ‰์„ ํฌ๊ฒŒ ๊น”๊ณ , ๊ทธ ์•ˆ์— stack์œผ๋กœ ์ดˆ๋ก์ƒ‰, ํŒŒ๋ž€์ƒ‰์„ ๊น๋‹ค.
๋”ฑ ์ •์˜ํ•œ ์ˆœ์„œ๋Œ€๋กœ ๊น”๊ณ  ๋ณด๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋ ‡๊ฒŒ ๋Œ๋ ค๋ณด๋ฉด

์˜๋„ํ•œ๋Œ€๋กœ ๋‚˜ํƒ€๋‚  ๊ฒƒ์ด๋‹ค.

์œ„์ฒ˜๋Ÿผ ๋ญ”๊ฐ€๋ฅผ ์ค‘์ฒฉ์‹œ์ผœ์„œ ํ‘œํ˜„ํ• ๋•Œ ์œ ์šฉํ•˜๋‹ค.

์˜ˆ์ œ ์ฝ”๋“œ

use iced::widget::{container, stack, text};
use iced::{Background, Color, Element, Length, Settings, Size};

pub struct MainApp {}

#[derive(Debug, Clone)]
pub enum Message {}

impl MainApp {
    pub fn new() -> Self {
        let app = Self {};

        app
    }
    pub fn theme(&self) -> iced::Theme {
        iced::Theme::Dracula
    }

    pub fn update(&mut self, message: Message) {
        match message {}
    }

    pub fn view(&self) -> Element<Message> {
        let content = container(stack![
            container(text("c"))
                .width(Length::Fill)
                .height(Length::Fill)
                .style(|_| {
                    let mut style = container::Style::default();
                    style.background = Some(Background::Color(Color::from_rgb8(0, 255, 0)));
                    style
                })
                .width(Length::Fixed(250.0))
                .height(Length::Fixed(250.0)),
            container(text("d"))
                .width(Length::Fill)
                .height(Length::Fill)
                .style(|_| {
                    let mut style = container::Style::default();
                    style.background = Some(Background::Color(Color::from_rgb8(0, 0, 255)));
                    style
                })
                .width(Length::Fixed(200.0))
                .height(Length::Fixed(200.0)),
        ])
        .width(Length::Fixed(300.0))
        .height(Length::Fixed(300.0))
        .style(|_| {
            let mut style = container::Style::default();

            style.background = Some(Background::Color(Color::from_rgb8(255, 0, 0)));

            style
        })
        .into();

        content
    }
}

impl Default for MainApp {
    fn default() -> Self {
        Self::new()
    }
}

fn main() -> iced::Result {
    let setting = Settings::default();

    iced::application("test", MainApp::update, MainApp::view)
        .settings(setting)
        .resizable(false)
        .window_size(Size::new(600.0, 600.0))
        .theme(MainApp::theme)
        .run()
}




์‘์šฉ: Modal ๊ตฌํ˜„

๊ธฐ๋ณธ ์ฐฝ ์œ„์— ์ž‘์€ ์ฐฝ์„ ๋„์šฐ๋Š”๊ฑธ ๋ณดํ†ต ๋ชจ๋‹ฌ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

Stack์˜ ํ”ํ•œ ์‘์šฉ๋ก€ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์ด๋ ‡๊ฒŒ ์ค‘์ฒฉ๋œ ์œ„์ ฏ์„ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์ด๋‹ค๋ณด๋‹ˆ, ๋ชจ๋‹ฌ ๊ฐ™์€๊ฑธ ๊ตฌํ˜„ํ•  ๋•Œ๋„ Stack์„ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

๋จผ์ € ๋ชจ๋‹ฌ์„ ํ˜„์žฌ ํ‘œ์‹œํ•˜๋Š” ์ƒํƒœ์ธ์ง€์— ๋Œ€ํ•œ ์ƒํƒœ๊ฐ’์ด ํ•„์š”ํ•˜๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋‹น์—ฐํžˆ ๋ชจ๋‹ฌ์„ ์ผœ๊ณ  ๋„๋Š” ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด์„œ๋„ ํ•ธ๋“ค๋ง์ด ๋˜์–ด์•ผํ•œ๋‹ค.


stack ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐ„๋‹จํ•œ ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.
์ด๋Ÿฌ๋ฉด ๊ธฐ์กด ์œ„์ ฏ์„ ์ „๋ถ€ ๋ฐ”๋‹ฅ์— ๊น”๊ณ , ๋ชจ๋‹ฌ์„ ์œ„์— ๊นŒ๋Š” ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑ์ด ๋œ๋‹ค.


view์—์„œ๋Š” ์ด๋Ÿฐ ์‹์œผ๋กœ ํ•ด์„œ, show_modal์ด ์ผœ์ ธ์žˆ์œผ๋ฉด ๋ฐฉ๊ธˆ ์ •์˜ํ•œ ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ชจ๋‹ฌ ๋ทฐ๋ฅผ ์ค‘์ฒฉํ•ด์„œ ๋„์šฐ๊ณ , ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ๋ชจ๋‹ฌ ์—†๋Š”์ฑ„๋กœ ํ‘œ์‹œํ•˜๋„๋ก ํ•˜๋ฉด ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ฒ„ํŠผ์œผ๋กœ ๋ชจ๋‹ฌ์„ ์ผœ๊ณ , ๋ชจ๋‹ฌ ๋ฐ–์„ ๋ˆ„๋ฅด๋ฉด ๋ชจ๋‹ฌ์ด ๊บผ์ง€๋„๋ก ํ–ˆ๋‹ค.

๊ทธ๋ ‡๊ฒŒ ์‹คํ–‰ํ•ด๋ณด๋ฉด

์˜๋„ํ•œ๋Œ€๋กœ ๋™์ž‘ํ•  ๊ฒƒ์ด๋‹ค.

์•„๋ž˜๋Š” ์ „์ฒด ์˜ˆ์ œ์ฝ”๋“œ๋‹ค.

use iced::widget::{button, center, container, mouse_area, opaque, stack, text};
use iced::{Color, Element, Length, Settings, Size};

pub fn create_modal<'a, Message>(
    base: impl Into<Element<'a, Message>>,
    content: impl Into<Element<'a, Message>>,
    on_blur: Message,
) -> Element<'a, Message>
where
    Message: Clone + 'a,
{
    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()
                }
            }))
            .on_press(on_blur)
        )
    ]
    .into()
}

pub struct MainApp {
    show_modal: bool,
}

#[derive(Debug, Clone)]
pub enum Message {
    OpenModal,
    CloseModal,
}

impl MainApp {
    pub fn new() -> Self {
        let app = Self { show_modal: false };

        app
    }
    pub fn theme(&self) -> iced::Theme {
        iced::Theme::Dracula
    }

    pub fn update(&mut self, message: Message) {
        match message {
            Message::OpenModal => {
                self.show_modal = !self.show_modal;
            }
            Message::CloseModal => {
                self.show_modal = false;
            }
        }
    }

    pub fn view(&self) -> Element<Message> {
        let content = container(button(text("Foo").size(12)).on_press(Message::OpenModal))
            .width(Length::Fill)
            .height(Length::Fill)
            .into();

        if self.show_modal {
            let modal_view = container(text("Bar").size(24))
                .width(250)
                .padding(10)
                .style(container::rounded_box);

            create_modal(content, modal_view, Message::CloseModal)
        } else {
            content
        }
    }
}

impl Default for MainApp {
    fn default() -> Self {
        Self::new()
    }
}

fn main() -> iced::Result {
    let setting = Settings::default();

    iced::application("test", MainApp::update, MainApp::view)
        .settings(setting)
        .resizable(false)
        .window_size(Size::new(200.0, 200.0))
        .theme(MainApp::theme)
        .run()
}