pub struct Setup<Msg> { /* private fields */ }Expand description
The application-owned state of a SetupWizard: which step it is on, what has been chosen on
the appearance step and how the Nerd Font install is going.
An application makes one at start, whether or not the wizard is needed, and asks
Setup::needed before drawing its own screen: the wizard opens while the application has no
settings file of its own, however much the family has already shared. Nothing is written until
it finishes, so closing the application half-way leaves the settings folder as it was and the
wizard comes again next start.
use qframe::i18n::I18n;
use qframe::prelude::*;
use qframe::storage::{Family, Settings};
use qframe::widgets::{Select, Setup, SetupMsg, SetupWizard};
struct Code {
setup: Setup<Msg>,
settings: Settings,
engine: usize,
}
#[derive(Debug, Clone, PartialEq)]
enum Msg {
Setup(SetupMsg),
Engine(usize),
Ready,
}
impl App for Code {
type Msg = Msg;
fn update(&mut self, msg: Msg) -> Command<Msg> {
match msg {
Msg::Setup(message) => self.setup.update(message, &mut self.settings),
Msg::Engine(engine) => {
self.engine = engine;
Command::none()
}
// The wizard wrote the shared keys and made the file; the application's own keys
// are its own to write.
Msg::Ready => {
self.settings.set("engine", self.engine as i64);
let _ = self.settings.save();
Command::none()
}
}
}
fn view(&self, ui: &mut View<'_, Msg>) {
if self.setup.needed() {
SetupWizard::new(&self.setup)
.step("Containers", |ui| {
let engines = Select::new(["podman", "docker"]).selected(Some(self.engine));
ui.add(engines.on_select(Msg::Engine));
})
.show(ui);
}
}
}
let family = Family::QUVYTA;
// An application calls `Setup::new(family, "code", &i18n, Msg::Setup)`; the example keeps to a
// folder of its own.
let setup = Setup::new_in(&folder, family, "code", &I18n::builtin(), Msg::Setup).on_finish(Msg::Ready);
let settings = Settings::open(folder.join("code.conf")).member_of(&family);
let mut app = Harness::new(Code { setup, settings, engine: 0 }, 60, 24);
assert!(app.screen().contains("In every Quvyta application"));
assert!(!folder.exists(), "nothing is written before the wizard finishes");Implementations§
Source§impl<Msg: Clone + Send + 'static> Setup<Msg>
impl<Msg: Clone + Send + 'static> Setup<Msg>
Sourcepub fn new(
family: Family,
app: impl Into<String>,
i18n: &I18n,
wrap: impl Fn(SetupMsg) -> Msg + Send + Sync + 'static,
) -> Self
pub fn new( family: Family, app: impl Into<String>, i18n: &I18n, wrap: impl Fn(SetupMsg) -> Msg + Send + Sync + 'static, ) -> Self
The setup of application app of family, on its first step, with every message of the
first step wrapped as wrap.
The shared preferences are resolved without writing anything
(Family::preferences_without_saving), so the appearance step comes filled with what the
family already shares, or with what this machine detects, and the user’s settings folder
stays as it is until the wizard finishes. An application that has taken over an older
settings file migrates it (Family::adopt) before making this, so a
migrated application is not asked again.
Sourcepub fn new_in(
config_dir: &Path,
family: Family,
app: impl Into<String>,
i18n: &I18n,
wrap: impl Fn(SetupMsg) -> Msg + Send + Sync + 'static,
) -> Self
pub fn new_in( config_dir: &Path, family: Family, app: impl Into<String>, i18n: &I18n, wrap: impl Fn(SetupMsg) -> Msg + Send + Sync + 'static, ) -> Self
new with config_dir as the family’s folder instead of this platform’s, for
a test or a demo that must leave the user’s own files alone.
Sourcepub fn on_finish(self, message: Msg) -> Self
pub fn on_finish(self, message: Msg) -> Self
The message the application is sent once the wizard has written the shared keys and made the application’s file: where the application writes its own keys.
Sourcepub fn install(self, install: Install) -> Self
pub fn install(self, install: Install) -> Self
Installs the Nerd Font symbols with install instead of Install::new, for a test or a
demo that must leave the user’s own fonts alone.
Sourcepub fn font_dirs(self, dirs: Vec<PathBuf>) -> Self
pub fn font_dirs(self, dirs: Vec<PathBuf>) -> Self
Looks for a Nerd Font in dirs instead of this system’s font folders, for a test or a demo.
Sourcepub fn needed(&self) -> bool
pub fn needed(&self) -> bool
Whether the wizard is still to be shown: the application has no settings file of its own and the wizard has not finished.
Sourcepub fn preferences(&self) -> &Preferences
pub fn preferences(&self) -> &Preferences
The shared preferences as the appearance step has them now, before anything is written.
Sourcepub fn update(
&mut self,
message: SetupMsg,
settings: &mut Settings,
) -> Command<Msg>
pub fn update( &mut self, message: SetupMsg, settings: &mut Settings, ) -> Command<Msg>
Applies message and returns the command that shows it: a theme, a language or an icon
mode is applied at once, so the wizard is drawn the way the user just chose. settings are
the application’s own settings as it holds them in memory; they take every shared key too,
so a later Settings::save writes what the wizard wrote instead of what the file said
before.
On SetupMsg::Finish the three shared keys are written with Family::set, each to the
family’s file or the application’s own by its box, and the application’s file is made. Only
then is the wizard over and the message of Setup::on_finish sent. A write that fails
leaves the wizard open and says why.
Trait Implementations§
Auto Trait Implementations§
impl<Msg> !RefUnwindSafe for Setup<Msg>
impl<Msg> !UnwindSafe for Setup<Msg>
impl<Msg> Freeze for Setup<Msg>
impl<Msg> Send for Setup<Msg>
impl<Msg> Sync for Setup<Msg>
impl<Msg> Unpin for Setup<Msg>
impl<Msg> UnsafeUnpin for Setup<Msg>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more