Skip to main content

Ui

Struct Ui 

Source
pub struct Ui { /* private fields */ }
Expand description

Proof that the current thread is set up for glasskit windows.

Create it once, on the thread that shows the windows, and give it to EventLoop::new, ChoicePopup::new, and Dialog::new. Each of them keeps a copy, so the setup stays while any window exists. Ui is not Send: windows must stay on the thread that made them, and the compiler enforces it.

Ui::new does this setup for the process and the thread:

  • It makes the process aware of the DPI of each monitor (per-monitor v2), unless the application manifest or an earlier call has set the DPI awareness.
  • It starts the Windows Runtime on the thread (single-threaded apartment).
  • It loads the standard common controls.
  • It creates the dispatcher queue that the popup animations need.

Implementations§

Source§

impl Ui

Source

pub fn new() -> Result<Self>

Set up the current thread, or get the setup that exists on it.

Examples found in repository?
examples/gallery.rs (line 46)
40fn main() -> glasskit::Result<()> {
41    let kind = std::env::args().nth(1).unwrap_or_default();
42    let Some(prompt) = prompt(&kind) else {
43        println!("kinds: {}", KINDS.join(", "));
44        return Ok(());
45    };
46    let ui = Ui::new()?;
47    let mut first = ChoicePopup::new(&ui, Placement::default())?;
48    if kind == "stack" {
49        first.show(&Prompt::new("A first question?", ["Yes", "No"]))?;
50    }
51    let mut popup = ChoicePopup::new(&ui, Placement::default())?;
52    println!("{:?}", popup.ask(&prompt)?.response);
53    Ok(())
54}
More examples
Hide additional examples
examples/quiz.rs (line 22)
21fn main() -> glasskit::Result<()> {
22    let ui = Ui::new()?;
23    let mut events = EventLoop::new(&ui)?;
24    let size = Icon::tray_size();
25    let icon = Icon::from_argb(size, vec![0xFF2E_86DE; (size * size) as usize])?;
26    let mut tray = Tray::new(&events, "Quiz", &icon)?;
27    tray.set_menu(&[
28        MenuItem::command(Command::AskNow, "Ask now"),
29        MenuItem::Separator,
30        MenuItem::Quit("Quit".into()),
31    ]);
32    let mut popup = ChoicePopup::new(&ui, Placement::default())?;
33    let mut next = SystemTime::now() + Duration::from_secs(60);
34    loop {
35        match events.next(Some(next))? {
36            Event::Quit => return Ok(()),
37            Event::Deadline | Event::Command(Command::AskNow) => {
38                next = SystemTime::now() + Duration::from_secs(60);
39                if !popup.is_showing() {
40                    let prompt = Prompt::new("What is 2 + 2?", ["3", "4", "5"])
41                        .marks(|clicked| answer_marks(clicked, 1))
42                        .auto_dismiss(Some(Duration::from_secs(30)));
43                    popup.show(&prompt)?;
44                }
45            }
46            Event::Popup(id) if id == popup.id() => {
47                if let Some(reply) = popup.take_reply() {
48                    println!("{:?}", reply.response);
49                }
50            }
51            _ => {}
52        }
53    }
54}
examples/dialog.rs (line 13)
12fn main() -> glasskit::Result<()> {
13    let ui = Ui::new()?;
14    let (width, height) = (420, 186);
15    let mut d = Dialog::new(&ui, "Profile", width, height)?;
16    let mut rows = Column::new(Bounds::new(0, 0, width, height).inset(16), 10);
17
18    let field = |row: Bounds| row.columns([Size::Fixed(110), Size::Fill(1)], 8);
19    let [label, control] = field(rows.next(26));
20    d.add_label("Name", label)?;
21    let name = d.add_edit(EditStyle::default(), control)?;
22    let [label, control] = field(rows.next(26));
23    d.add_label("Language", label)?;
24    let language = d.add_drop_down(control)?;
25    d.set_items(language, &["English", "Cantonese", "Japanese"]);
26    d.set_selected(language, Some(0));
27    let news = d.add_check("Send me news", rows.next(26))?;
28
29    let [_, save, cancel] = rows
30        .next(30)
31        .columns([Size::Fill(1), Size::Fixed(96), Size::Fixed(96)], 8);
32    let save = d.add_button("Save", save)?;
33    let cancel = d.add_button("Cancel", cancel)?;
34
35    d.run(|d, event| match event {
36        Event::Clicked(id) if id == save => {
37            println!(
38                "{} / {:?} / news: {}",
39                d.text(name),
40                d.selected(language),
41                d.checked(news)
42            );
43            Flow::Close
44        }
45        Event::Submit => Flow::Continue,
46        Event::Clicked(id) if id == cancel => Flow::Close,
47        Event::Close => Flow::Close,
48        _ => Flow::Continue,
49    })?;
50    Ok(())
51}
examples/kanban.rs (line 24)
23fn main() -> glasskit::Result<()> {
24    let ui = Ui::new()?;
25    let mut events: EventLoop<()> = EventLoop::new(&ui)?;
26    let mut window = Window::new(&ui, "Kanban", 820.0, 520.0)?;
27    window.set_min_size(560.0, 360.0);
28
29    let mut board = Board::new(&mut window, &["To do", "Doing", "Done"]);
30    for (lane, title, body) in CARDS {
31        board.add_card(&mut window, lane, CardData::new(title, body));
32    }
33    let pinned = CardData {
34        pinned: true,
35        ..CardData::new("Ask for the budget", "")
36    };
37    board.add_card(&mut window, 1, pinned);
38
39    let title = window.add(Text::new("Board").style(TextStyle::Title));
40    let gap = window.add(Spacer::fill());
41    let archived = window.add(Button::new("Show archived"));
42    let top = window.add(Row::new().child(title).child(gap).child(archived));
43    let root = window.add(
44        Column::new()
45            .padding(Insets::all(16.0))
46            .gap(12.0)
47            .child(top)
48            .child(board.widget()),
49    );
50    window.set_root(root);
51    window.show();
52
53    loop {
54        match events.next(None)? {
55            Event::Window(id) if id == window.id() => {
56                while let Some(event) = window.next_event() {
57                    match event {
58                        WindowEvent::CloseRequested => return Ok(()),
59                        WindowEvent::Clicked(id) if id == archived => {
60                            let show = !board.show_archived();
61                            board.set_show_archived(&mut window, show);
62                            let label = if show {
63                                "Hide archived"
64                            } else {
65                                "Show archived"
66                            };
67                            window.set_text(archived, label);
68                        }
69                        event => {
70                            if let Some(change) = board.handle(&ui, &mut window, &event)? {
71                                println!("{}", describe(&board, &change));
72                            }
73                        }
74                    }
75                }
76            }
77            Event::Quit => return Ok(()),
78            _ => {}
79        }
80    }
81}
examples/sidebar.rs (line 23)
22fn main() -> glasskit::Result<()> {
23    let ui = Ui::new()?;
24    let mut events: EventLoop<()> = EventLoop::new(&ui)?;
25    let mut window = Window::new(&ui, "Side bar", 560.0, 360.0)?;
26    window.set_min_size(360.0, 260.0);
27
28    let items = PAGES.map(|(name, icon)| window.add(NavItem::new(name).icon(icon)));
29    let pages = PAGES.map(|(name, _)| {
30        let title = window.add(Text::new(name).style(TextStyle::Title));
31        window.add(Column::new().padding(Insets::all(16.0)).child(title))
32    });
33    let gap = window.add(Spacer::fill());
34    let mode = match std::env::args().nth(1).as_deref() {
35        Some("icons") => SideMode::Icons,
36        Some("collapsed") => SideMode::Collapsed,
37        _ => SideMode::Expanded,
38    };
39    let side = window.add(
40        SideBar::new()
41            .title("glasskit")
42            .expanded_width(180.0)
43            .mode(mode)
44            .gap(4.0)
45            .child(items[0])
46            .child(items[1])
47            .child(gap)
48            .child(items[2]),
49    );
50    let stack = window.add(Stack::new().width(Length::Fill(1.0)).children(pages));
51    let root = window.add(
52        Row::new()
53            .padding(Insets::all(8.0))
54            .gap(8.0)
55            .align(Align::Stretch)
56            .child(side)
57            .child(stack),
58    );
59    window.set_root(root);
60    let show = |window: &mut Window, shown: usize| {
61        for (i, (item, page)) in items.into_iter().zip(pages).enumerate() {
62            window.set_selected(item, i == shown);
63            window.set_visible(page, i == shown);
64        }
65    };
66    show(&mut window, 0);
67    window.show();
68
69    loop {
70        match events.next(None)? {
71            Event::Window(id) if id == window.id() => {
72                while let Some(event) = window.next_event() {
73                    match event {
74                        WindowEvent::Clicked(id) => {
75                            if let Some(shown) = items.iter().position(|&item| id == item) {
76                                show(&mut window, shown);
77                            }
78                        }
79                        WindowEvent::SideModeChanged(id) if id == side => {
80                            println!("{:?}", window.side_mode(side));
81                        }
82                        WindowEvent::CloseRequested => return Ok(()),
83                        _ => {}
84                    }
85                }
86            }
87            Event::Quit => return Ok(()),
88            _ => {}
89        }
90    }
91}
examples/window.rs (line 16)
15fn main() -> glasskit::Result<()> {
16    let ui = Ui::new()?;
17    let mut events: EventLoop<()> = EventLoop::new(&ui)?;
18    let mut window = Window::new(&ui, "glasskit", 420.0, 330.0)?;
19    window.set_min_size(320.0, 290.0);
20    match std::env::args().nth(1).as_deref() {
21        Some("glass") => window.set_material(Material::Glass),
22        Some("solid") => window.set_material(Material::Solid),
23        _ => {}
24    }
25
26    let title = window.add(Text::new("Settings").style(TextStyle::Title));
27    let note = window.add(Text::new(
28        "Widgets lay out in rows and columns, and the window follows the display scale.",
29    ));
30    let count = window.add(Text::new("Count: 0").style(TextStyle::BodyStrong));
31    let add = window.add(Button::new("Add one"));
32    let counter = window.add(Row::new().gap(12.0).child(count).child(add));
33    let card = window.add(Card::new().child(counter));
34    let name = window.add(TextBox::new().placeholder("Your name").max_length(40));
35    let spacer = window.add(Spacer::fill());
36    let cancel = window.add(Button::new("Cancel"));
37    let ok = window.add(Button::new("OK").accent());
38    let buttons = window.add(Row::new().gap(8.0).child(spacer).child(cancel).child(ok));
39    let gap = window.add(Spacer::fill());
40    let root = window.add(
41        Column::new()
42            .padding(Insets::all(24.0))
43            .gap(12.0)
44            .child(title)
45            .child(note)
46            .child(card)
47            .child(name)
48            .child(gap)
49            .child(buttons),
50    );
51    window.set_root(root);
52    window.show();
53
54    let mut n = 0;
55    loop {
56        match events.next(None)? {
57            Event::Window(id) if id == window.id() => {
58                while let Some(event) = window.next_event() {
59                    match event {
60                        WindowEvent::Clicked(b) if b == add => {
61                            n += 1;
62                            window.set_text(count, &format!("Count: {n}"));
63                            println!("count {n}");
64                        }
65                        WindowEvent::Clicked(b) if b == ok => {
66                            println!("ok {}", window.text(name));
67                            return Ok(());
68                        }
69                        WindowEvent::Submitted(b) if b == name => {
70                            println!("ok {}", window.text(name));
71                            return Ok(());
72                        }
73                        WindowEvent::Clicked(b) if b == cancel => return Ok(()),
74                        WindowEvent::Key(k) if k.is_plain(Key::ESCAPE) => {
75                            println!("escape");
76                            return Ok(());
77                        }
78                        WindowEvent::CloseRequested => return Ok(()),
79                        _ => {}
80                    }
81                }
82            }
83            Event::Quit => return Ok(()),
84            _ => {}
85        }
86    }
87}

Trait Implementations§

Source§

impl Clone for Ui

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Ui

§

impl !Send for Ui

§

impl !Sync for Ui

§

impl !UnwindSafe for Ui

§

impl Forget for Ui

§

impl Freeze for Ui

§

impl Move for Ui

§

impl Unpin for Ui

§

impl UnsafeUnpin for Ui

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.