Skip to main content

Crate glasskit

Crate glasskit 

Source
Expand description

Native Windows UI with a glass look: a tray icon and menu, a frosted-glass popup, themed dialogs, and helpers for tray apps.

  • events: EventLoop, the main loop of the app. It sleeps until a menu command, the end of a popup, a change in a dialog, a deadline, or an unlock of the session.
  • tray: an icon in the notification area with a menu.
  • popup: a frosted-glass popup with a question and choice buttons. It fades in without taking the keyboard focus, can show whether a choice was correct, and can dismiss itself.
  • dialog: a small modal window made of standard controls, in the same colors.
  • layout: rows and columns that place the controls of a dialog.
  • window and widget: a glass window with a tree of widgets.
  • kanban: a board with lanes of cards that the user drags, edits, pins, and archives.
  • placement: where a window shows, as fractions of the free space of the screen.
  • autostart, presence, process, single_instance, and show_error: small helpers that tray apps often need.

All windows follow the Windows light or dark app mode and the display scale.

§Threads

Make one Ui on the thread that shows the windows, and make all windows on that thread. Ui is not Send, so the compiler stops a window from going to another thread. The thread must run EventLoop::next, which handles the window messages of all windows of the thread. An app without a tray can use ChoicePopup::ask and Dialog::run instead: each of them has a message loop of its own and returns when its window ends.

§Example

A tray app that asks a question each minute and on “Ask now”. The same program is in examples/quiz.rs.

use std::time::{Duration, SystemTime};

use glasskit::Ui;
use glasskit::events::{Event, EventLoop};
use glasskit::placement::Placement;
use glasskit::popup::{ChoicePopup, Mark, Prompt};
use glasskit::tray::{Icon, MenuItem, Tray};

#[derive(Debug, Clone, PartialEq, Eq)]
enum Command {
    AskNow,
}

fn main() -> glasskit::Result<()> {
    let ui = Ui::new()?;
    let mut events = EventLoop::new(&ui)?;
    let size = Icon::tray_size();
    let icon = Icon::from_argb(size, vec![0xFF2E_86DE; (size * size) as usize])?;
    let mut tray = Tray::new(&events, "Quiz", &icon)?;
    tray.set_menu(&[
        MenuItem::command(Command::AskNow, "Ask now"),
        MenuItem::Separator,
        MenuItem::Quit("Quit".into()),
    ]);
    let mut popup = ChoicePopup::new(&ui, Placement::default())?;
    let mut next = SystemTime::now() + Duration::from_secs(60);
    loop {
        match events.next(Some(next))? {
            Event::Quit => return Ok(()),
            Event::Deadline | Event::Command(Command::AskNow) => {
                next = SystemTime::now() + Duration::from_secs(60);
                if !popup.is_showing() {
                    let prompt = Prompt::new("What is 2 + 2?", ["3", "4", "5"])
                        .marks(|clicked| answer_marks(clicked, 1))
                        .auto_dismiss(Some(Duration::from_secs(30)));
                    popup.show(&prompt)?;
                }
            }
            Event::Popup(id) if id == popup.id() => {
                if let Some(reply) = popup.take_reply() {
                    println!("{:?}", reply.response);
                }
            }
            _ => {}
        }
    }
}

/// Mark the correct answer good and a wrong click bad.
fn answer_marks(clicked: usize, correct: usize) -> Vec<(usize, Mark)> {
    let mut marks = vec![(correct, Mark::Good)];
    if clicked != correct {
        marks.push((clicked, Mark::Bad));
    }
    marks
}

Re-exports§

pub use error::Error;
pub use error::Result;

Modules§

autostart
Start the app when the user signs in to Windows.
dialog
A small modal window built from standard Windows controls, in the same colors as the popup. The app places the controls and handles the events. glasskit knows nothing about the content.
error
The error type of glasskit.
events
The main loop of an app: one loop for all trays, popups, and dialogs of a thread.
kanban
A kanban board for a Window: lanes side by side, each with a stack of cards.
layout
Rows and columns for a Dialog, so that its controls need no hand-placed coordinates.
placement
Where a window shows in an area, as fractions of the free space in that area.
popup
A frosted-glass popup that asks a question with choice buttons.
presence
Whether the user can see a popup now.
process
Settings of the whole process.
tray
A notification-area (tray) icon with a menu.
widget
Widgets for a Window: text, buttons, text boxes, cards, and the rows, columns, and stacks that place them.
window
A general app window with a glass look, and the widgets in it.

Structs§

InstanceGuard
Proof that this process is the only one with a name in the user session. The name is free again when the guard is dropped or the process ends.
Ui
Proof that the current thread is set up for glasskit windows.

Functions§

show_error
Show an error in a message box, and wait until the user closes it. It needs no Ui, so it also works before the setup or after a failed setup.
single_instance
Take name for this process in the user session. It gives None if another process has the name, for example a second start of the same app.