Skip to main content

NodeMut

Struct NodeMut 

Source
pub struct NodeMut<'a, Msg> { /* private fields */ }
Expand description

Adjusts the node just added. Every method changes the node in place, so the result can be ignored or chained.

Implementations§

Source§

impl<'a, Msg> NodeMut<'a, Msg>

Source

pub fn id(self, name: impl Into<String>) -> Self

Names the node. Name widgets whose position among their siblings can change (list rows, optional widgets) so their state and focus follow them.

Source

pub fn width(self, width: Length) -> Self

Sets the width.

Source

pub fn height(self, height: Length) -> Self

Sets the height.

Source

pub fn fill(self) -> Self

Takes all space left in both directions.

Source

pub fn fill_width(self) -> Self

Takes all width left.

Source

pub fn fill_height(self) -> Self

Takes all height left.

Source

pub fn padding(self, padding: Padding) -> Self

Keeps padding free inside the node.

Source

pub fn gap(self, cells: u16) -> Self

Leaves cells between the children of a row or column.

Source

pub fn justify(self, align: Align) -> Self

Places children along the main axis of a row or column (both axes of a stack).

Source

pub fn selectable(self, selectable: bool) -> Self

Whether a mouse drag may select text in this node. Nothing is selectable unless asked: true makes the node a selection region, so a drag that starts inside it selects text within the node only (widgets such as CodeView and Markdown are regions by themselves). false keeps selection out of the node and everything inside it, also out of regions within it, e.g. for a secret shown inside a selectable log.

Source

pub fn align(self, align: Align) -> Self

Places children across the main axis of a row or column.

Source§

impl<Msg: Clone + 'static> NodeMut<'_, Msg>

Source

pub fn on_action( self, scope: Scope, action: impl Into<String>, message: Msg, ) -> Self

While keyboard focus is on this node or inside it, a key bound to the keymap action action of scope sends message instead of reaching App::action.

This is how an application tells where a shortcut was pressed. With focus elsewhere the same key reaches App::action as usual, so one key can mean two things: leave a terminal while inside it, go back into it from outside. The focus in force when the key arrives decides, however it got there (tab, a click, Command::focus), so nothing has to be tracked in application state.

The innermost node that answers the action wins. The key must first get past the focused widgets: a widget that uses it (a text field typing a character) keeps it, and a Terminal lets it out only for actions named with its pass_through. The actions the runtime owns (quit, focus-next, focus-prev, debug, copy, paste, toggle-panel) are not answered here; the keys of copy and paste are claimed with on_clipboard instead. Call once per action.

use qframe::env::Env;
use qframe::prelude::*;
use qframe::widgets::TextInput;

#[derive(Clone, Debug, PartialEq)]
enum Msg {
    Leave,
    Enter,
}

struct Editor;

impl App for Editor {
    type Msg = Msg;

    fn update(&mut self, msg: Msg) -> Command<Msg> {
        match msg {
            Msg::Leave => Command::focus("files"),
            Msg::Enter => Command::focus("note"),
        }
    }

    fn view(&self, ui: &mut View<'_, Msg>) {
        ui.add(List::new(["notes.md", "todo.md"].map(ListItem::new))).id("files");
        ui.add(TextInput::new("")).id("note").on_action(Scope::App, "switch", Msg::Leave);
    }

    // Reached only while focus is outside the note.
    fn action(&self, name: &str) -> Option<Msg> {
        (name == "switch").then_some(Msg::Enter)
    }
}

let mut env = Env::builtin();
env.keymap_mut().bind(Scope::App, "switch", &["alt+s".parse().unwrap()]);
let mut app = Harness::with_env(Editor, env, 30, 3);
app.press("alt+s");
assert!(app.is_focused("note"));
app.press("alt+s");
assert!(app.is_focused("files"));
Source

pub fn on_clipboard(self, key: ClipboardKey, message: Msg) -> Self

While keyboard focus is on this node or inside it, the clipboard key key sends message: a list of things other than text, such as a file manager’s rows, cuts, copies and pastes its own entries with the keys a text field uses for text.

The keys are claimed, not taken away. Every place text is copied from keeps them first:

  • Text selected with the mouse is what Ctrl+C copies while it is there, wherever the focus is, and while it is there Ctrl+X and Ctrl+V are not claimed either: the person is working with that text, not with the node.
  • The focused widget sees the key before the node does, so a text field inside the node copies and cuts its own text. Pasting into a field goes through the runtime’s paste action, which a claim of ClipboardKey::Paste answers first, so a node that holds a field claims only the keys it does not share with it.
  • With focus outside the node, the keys do what they do without it.

This rides on the same answering as on_action, one step after it in the key’s way and for the runtime’s own copy and paste, which on_action never answers, and for Ctrl+X, which has no keymap action. A widget could match the chords in its own key handling instead, as a text field does, but then every list, table and grid would need a way to be told what the keys mean; claiming them on the node gives that to anything that can be focused. The innermost node that claims a key wins. Call once per key.

use qframe::prelude::*;
use qframe::widget::ClipboardKey;

#[derive(Clone, Debug, PartialEq)]
enum Msg {
    Copy,
}

struct Shelf {
    copied: bool,
}

impl App for Shelf {
    type Msg = Msg;

    fn update(&mut self, msg: Msg) -> Command<Msg> {
        match msg {
            Msg::Copy => self.copied = true,
        }
        Command::none()
    }

    fn view(&self, ui: &mut View<'_, Msg>) {
        ui.add(List::new(["a.txt", "b.txt"].map(ListItem::new)))
            .id("shelf")
            .on_clipboard(ClipboardKey::Copy, Msg::Copy);
    }
}

let mut app = Harness::new(Shelf { copied: false }, 20, 3);
app.press("ctrl+c");
assert!(!app.app().copied, "nothing is focused yet");
app.press("tab").press("ctrl+c");
assert!(app.app().copied);
Source§

impl<Msg: 'static> NodeMut<'_, Msg>

Source

pub fn wrap(self, wrap: bool) -> Self

Moves the children of a row that do not fit to the next line, instead of letting them run past the row’s edge. Off by default; a row whose children fit lays out exactly as it does without it.

Lines are filled in order: each child takes the width it measures, and a child that does not fit after the ones already on the line starts the next line. A child wider than the whole row gets a line of its own and the row’s width, where it narrows or cuts as it does in any row too narrow for it. The row measures as tall as all its lines, so the widgets after it move down.

Every line is laid out as a row of its own: gap falls between the children of a line, never at its start or end; justify places each line in the room it leaves; a spacer or another filling child takes what is left on its own line. A spacer stays on the line of the child before it; when that line has no room even for the gap before it, the spacer is left out, since at the start of the next line it would only push that line away from the edge.

Lines touch; line_gap puts empty rows between them. The option has no effect on anything but a row.

use qframe::prelude::*;

fn actions(ui: &mut View<'_, ()>) {
    ui.row(|ui| {
        ui.add(Button::new("Install").on_press(()));
        ui.add(Button::new("Show the command").on_press(()));
        ui.add(Button::new("Cancel").on_press(()));
    })
    .gap(1)
    .wrap(true);
}
Source

pub fn line_gap(self, rows: u16) -> Self

Leaves rows empty rows between the lines of a row that wraps. A row that fits on one line has no gap under it.

Auto Trait Implementations§

§

impl<'a, Msg> !RefUnwindSafe for NodeMut<'a, Msg>

§

impl<'a, Msg> !Send for NodeMut<'a, Msg>

§

impl<'a, Msg> !Sync for NodeMut<'a, Msg>

§

impl<'a, Msg> !UnwindSafe for NodeMut<'a, Msg>

§

impl<'a, Msg> Freeze for NodeMut<'a, Msg>
where &'a mut Node<Msg>: Freeze,

§

impl<'a, Msg> Unpin for NodeMut<'a, Msg>
where &'a mut Node<Msg>: Unpin,

§

impl<'a, Msg> UnsafeUnpin for NodeMut<'a, Msg>
where &'a mut Node<Msg>: UnsafeUnpin,

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> 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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
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.