File Dialogs

Introduction

WIP. The dialog API is functional on all platforms, but every call is synchronous and blocks the calling thread. An async variant is planned; signatures here are stable.

Azul ships native message boxes, file pickers, folder pickers, and a color chooser. Each call shows the platform's native dialog chrome.

use azul::prelude::*;

let path = FileDialog::open_file(
    "Open a file".into(),
    OptionString::None,
    OptionFileTypeList::None,
);
match path.into_option() {
    Some(p) => MsgBox::info(format!("You picked {}", p.as_str()).into()),
    None    => MsgBox::info("Cancelled".into()),
};

Types

  • MsgBox: message boxes (ok, ok_cancel, yes_no, info).
  • FileDialog: open, save, multi-select file pickers, and the folder picker.
  • ColorPickerDialog: RGB color picker, returns OptionColorU.

Supporting enums:

  • MsgBoxIcon with variants Info, Warning, Error, Question. Used by every MsgBox call.
  • OkCancel with variants Ok, Cancel. Used by MsgBox::ok_cancel for the default-highlighted button and the return value.
  • YesNo with variants Yes, No. Used by MsgBox::yes_no the same way.
  • FileTypeList with document_types: StringVec and document_descriptor, used to pass FileDialog filters.

Calling from a callback

Dialog functions block the entire window event loop until the user dismisses the dialog. That's almost always what you want from inside a callback. The user just clicked File → Open and doesn't expect to interact with the underlying window until they pick something.

use azul::prelude::*;

extern "C" fn on_open_clicked(_data: RefAny, _info: CallbackInfo) -> Update {
    let filter = FileTypeList {
        document_types: StringVec::from_vec(vec![
            "png".into(),
            "jpg".into(),
            "jpeg".into(),
        ]),
        document_descriptor: "Image files".into(),
    };

    let picked = FileDialog::open_file(
        "Pick an image".into(),
        OptionString::None,
        OptionFileTypeList::Some(filter),
    );

    match picked.into_option() {
        Some(_path) => Update::RefreshDom,
        None        => Update::DoNothing,
    }
}

OptionString::None for default_path lets the OS pick a sensible starting directory. Pass OptionString::Some(...) to override.

File pickers

The four picker variants on FileDialog:

fn open_file(
    title: AzString,
    default_path: OptionString,
    filter_list: OptionFileTypeList,
) -> OptionString;

fn open_directory(
    title: AzString,
    default_path: OptionString,
) -> OptionString;

fn open_multiple_files(
    title: AzString,
    default_path: OptionString,
    filter_list: OptionFileTypeList,
) -> OptionStringVec;

fn save_file(
    title: AzString,
    default_path: OptionString,
) -> OptionString;

Each returns None on cancel. Filters are extension-only: pass bare extensions like "png", "jpg" (no leading dot, no glob), plus a human-readable label. open_directory and save_file ignore filters.

Message boxes

use azul::prelude::*;

MsgBox::ok("Saved".into(), "File written.".into(), MsgBoxIcon::Info);

let proceed = MsgBox::ok_cancel(
    "Confirm".into(),
    "Overwrite existing file?".into(),
    MsgBoxIcon::Warning,
    OkCancel::Cancel,
);
if proceed == OkCancel::Ok {
    // ...
}

let answer = MsgBox::yes_no(
    "Quit".into(),
    "Discard unsaved changes?".into(),
    MsgBoxIcon::Question,
    YesNo::No,
);

MsgBox::info("All done.".into());

Color picker

use azul::prelude::*;

let initial = OptionColorU::Some(ColorU { r: 37, g: 99, b: 235, a: 255 });
let picked = ColorPickerDialog::open("Pick a color".into(), initial);

match picked.into_option() {
    Some(c) => println!("rgb({}, {}, {})", c.r, c.g, c.b),
    None    => println!("cancelled"),
}

The picker returns RGB only; alpha is forced to opaque. Pass OptionColorU::None to start at black.

Limitations

  • All dialog calls block the calling thread until dismissed. Inside a callback this stops event delivery to every window in your app. For long-running operations triggered after the dialog closes, spawn a background thread.
  • Filter format is extension-only.
  • Pass one FileTypeList per call. If you need multiple labelled groups, present them in a custom in-window picker instead.

Coming Up Next

Back to guide index