Use of moved value in for loop

Hello

I am making a basic calculator in OrbTk. I'm now making the buttons with the ciphers on. For this I use a 4x4 grid.

I could easily do this by programming all the buttons manually:

                grid.child(
                    Button::create()
                        .text("1")
                        .attach(Grid::column(0))
                        .attach(Grid::row(2))
                        .build(ctx)
                )
                .child(
                    Button::create()
                        .text("2")
                        .attach(Grid::column(1))
                        .attach(Grid::row(2))
                        .build(ctx)
                )
                .child(
                    Button::create()
                        .text("3")
                        .attach(Grid::column(2))
                        .attach(Grid::row(2))
                        .build(ctx)
                )
                .child(
                    Button::create()
                        .text("4")
                        .attach(Grid::column(0))
                        .attach(Grid::row(1))
                        .build(ctx)
                )
                .build(ctx)

But I want to do this in a loop (because that's cooler). Ignore the attach() function by the way. It's used to decide in what cell of the grid to place the button. I'll implement that later by using a nested loop.

This is my attempt:

use orbtk::*;

widget!(MainView);

impl Template for MainView {
    fn template(self, _: Entity, ctx: &mut BuildContext) -> Self {

        //Initializing Grid
        let mut grid = Grid::create(); 

        //Configuring grid (amount of rows and columns)
        grid
            .columns(
                Columns::create()
                    .column("*")
                    .column("*")
                    .column("*")
                    .column("*")
                    .build()
            )
            .rows(
                Rows::create()
                    .row("*")
                    .row("*")
                    .row("*")
                    .row("*")
                    .build()
            );
       
        //Adding all buttons from 1-9 to the grid
        //in calculator format
        for i in 0..10 {
            grid.child(
                Button::create()
                    .text(i.to_string())
                    .build(ctx)
            );
        }

        self.name("MainView").child(
                /*
                 * WHAT I WANT TO AUTOMATE IN THE LOOP:
                grid.child(
                    Button::create()
                        .text("1")
                        .attach(Grid::column(0))
                        .attach(Grid::row(2))
                        .build(ctx)
                )
                .child(
                    Button::create()
                        .text("2")
                        .attach(Grid::column(1))
                        .attach(Grid::row(2))
                        .build(ctx)
                )
                .child(
                    Button::create()
                        .text("3")
                        .attach(Grid::column(2))
                        .attach(Grid::row(2))
                        .build(ctx)
                )
                .child(
                    Button::create()
                        .text("4")
                        .attach(Grid::column(0))
                        .attach(Grid::row(1))
                        .build(ctx)
                )
                .build(ctx)
                */

            grid.build(ctx)
        )
   } 
}

fn main() {
    Application::new()
        .window(|ctx| {
            Window::create()
                .title("OrbTk - Calculator")
                .position((100.0, 100.0))
                .size(420.0, 730.0)
                .child(MainView::create().build(ctx))
                .build(ctx)
        })
        .run();
}

Error:

error[E0382]: use of moved value: `grid`
  --> src/main.rs:34:13
   |
10 |         let mut grid = Grid::create();
   |             -------- move occurs because `grid` has type `orbtk_widgets::grid::Grid`, which does not implement the `Copy` trait
...
13 |         grid
   |         ---- value moved here
...
34 |             grid.child(
   |             ^^^^ value moved here, in previous iteration of loop

error: aborting due to previous error

This seemed a very similar problem to this question but the solution Andrew suggested there didn't work for me.

        //Solution provided in the other question
        //Doesn't work for this problem though.
        for i in 0..10 {
            grid = grid.child(
                Button::create()
                    .text(i.to_string())
                    .build(ctx)
            );
        }

Error I get with that attempt:

error[E0382]: use of moved value: `grid`
  --> src/main.rs:34:20
   |
10 |         let mut grid = Grid::create();
   |             -------- move occurs because `grid` has type `orbtk_widgets::grid::Grid`, which does not implement the `Copy` trait
...
13 |         grid
   |         ---- value moved here
...
34 |             grid = grid.child(
   |                    ^^^^ value used here after move

error: aborting due to previous error

So, do I fix this? Thanks!

It is indeed the same, you just forgot one place where you need an grid = grid.foo() before the loop.

2 Likes

So what exactly do I need to do on the first line here?

        //Adding all buttons from 1-9 to the grid
        //in calculator format
        grid = grid.foo();
        for i in 0..10 {
            grid = grid.child(
                Button::create()
                    .text(i.to_string())
                    .build(ctx)
            );
        }

With what do I need to replace foo()? I tried as_ref() and variants to make a kind of pointer, but that function is not found.

I was referring to this part:

//Configuring grid (amount of rows and columns)
grid = grid
    .columns(
        Columns::create()
            .column("*")
            .column("*")
            .column("*")
            .column("*")
            .build()
    )
    .rows(
        Rows::create()
            .row("*")
            .row("*")
            .row("*")
            .row("*")
            .build()
    );
1 Like

Of course, thanks!!

PS.
Final code to generate the calculator buttons for might someone be curious.

        //Adding all buttons from 1-9 to the grid
        //in calculator format
        let mut counter : u8 = 9;
        for i in 0..3 {
            for j in 0..3 {
                grid = grid.child(
                    Button::create()
                        .text(counter.to_string())
                        .attach(Grid::column(j))
                        .attach(Grid::row(i))
                        .build(ctx)
                );

                counter = counter - 1;
            }
        }