Appearance
Dialogs
Dialogs ask the user for something and reply later. Barton shows native file dialogs, and any window can act as a dialog that returns a result.
File dialogs
An event handler that takes a FileDialog can show one. The dialog doesn't block the app, and the user's choice arrives in the callback passed to then:
cpp
MenuItem {
"Open...",
on_activate = [](FileDialog dialog) {
dialog.show(OpenFile {}.with_filter("Images", "png;jpg"))
.then([](const FileDialogEvent& event, State& state) {
if (const auto* path = event.path())
state.image = *path;
});
},
}The callback follows the same rules as any handler, so it can take state, windows or any other parameter.
There are three kinds of file dialog:
| Kind | Asks for |
|---|---|
OpenFile | One or more existing files, with with_many() for several |
SaveFile | A path to save to |
OpenFolder | One or more folders |
Each can set a title, a starting location and the button labels, and the file dialogs can filter by type:
cpp
SaveFile {}
.with_title("Export Level")
.with_location(state.project_dir)
.with_accept("Export")
.with_filter("Level", "json")Responses
A file dialog ends in one of three ways: the user picks something, cancels, or the dialog fails to open.
cpp
.then([](const FileDialogEvent& event, State& state) {
if (const auto* accepted = event.accepted())
state.files = accepted->paths;
else if (event.cancelled())
state.status = "Nothing chosen";
else if (const auto* error = event.error())
state.status = error->message();
})When only one path matters, path() returns the first one picked, or nothing.
Custom dialogs
A window becomes a dialog by declaring the type of result it returns. Opening it then gives a pending reply, and the window answers by closing with a value:
cpp
class ConfirmDelete : public Window {
public:
using Result = bool;
View render() const {
return Row {
gap = 8_px,
Container {
on_click = [](CurrentWindow window) { window.close_with(true); },
Text { "Delete" },
},
Container {
on_click = [](CurrentWindow window) { window.close_with(false); },
Text { "Cancel" },
},
};
}
};cpp
on_activate = [](Windows& windows) {
windows.open<ConfirmDelete>({ .title = "Delete layer?", .width = 320, .height = 140 })
.then([](bool confirmed, State& state) {
if (confirmed)
state.layers.pop_back();
});
}If the window is closed without a result, such as from its title bar, a second callback receives Dismissed:
cpp
.then(
[](bool confirmed, State& state) { ... },
[](Dismissed, State& state) { state.status = "Kept the layer"; }
)