rustfltk

Call same button inside different callbacks


I'm trying to make a basic software in Rust using the GUI Library FLTK. See my code at Pastebin. I created a button called input1 at line 18. I need to call this button inside two different callbacks. But the first callback get the button ownership. So I get an error at line 41, on creating the second callback. How could I create this button and call it inside the different callbacks?

https://pastebin.com/LKdfeKA3?fbclid=IwAR30JmY37ZIkmSMBzcwj0YuoWMLaLsMQwDtKJUgLUP01A-lm9d28bXzk0OM

use std::{borrow::BorrowMut, rc::Rc, cell::RefCell, sync::{Arc, Mutex}};
 
use fltk::{*, app, button::{Button, LightButton}, frame::Frame, prelude::*, window::Window, enums::*,  text::{TextBuffer, TextDisplay}};
use fltk_calendar::calendar;
use fltk::button::CheckButton;
use chrono::prelude::*;
 
fn main() {
 
    let mut data_geracao_str = String::new();
    let mut data_geracao_inicio_str = String::new();
 
    let app = app::App::default();
    let mut wind = Window::new(20, 40, 800, 600, "Gerador de Arquivos Diários - Armarinhos Fernando");
 
 
    let mut _titulo1 = Frame::new(30, 33, 150, 10, "Data Inicial");
    let mut input1 =  input::Input::new(160,25,150,35,"");
    let mut but_cal1 = button::Button::new(320, 25, 80, 36, "Calendário");
 
    but_cal1.set_label_size(10);
    input1.deactivate();
    but_cal1.deactivate();
 
 
    but_cal1.set_callback(   move|_| {
        let cal = calendar::Calendar::default();
        let naive_date = cal.get_date();
        if let Some(naive_date) = naive_date {
            data_geracao_inicio_str.clear();
            data_geracao_inicio_str.push_str(naive_date.format("%Y-%m-%d").to_string().as_str());
            input1.set_value(data_geracao_inicio_str.as_str());
            data_geracao_inicio_str.push_str(" 00:00:00 +00:00");
 
            println!("{:?}",&data_geracao_inicio_str);
 
        }
    });
 
    let mut check_input =  CheckButton::new(415,25,250,40,"Data Inicio Diferente");
    check_input.set_callback( |check1|{
        if check1.is_checked(){
            input1.set_value("");
            //input1.set_value("");
            //&input1.activate();
            but_cal1.activate();
        }else{
            //&input1.set_value("");
            //&input1.deactivate();
            but_cal1.deactivate();
        }
    });
 
    let mut _titulo2 = Frame::new(30, 95, 150, 10, "Data Final");
    let mut input2 =  input::Input::new(160,85,150,35,"");
    let mut but_cal2 = button::Button::new(320, 85, 80, 36, "Calendário");
    but_cal2.set_label_size(10);   
 
    let mut btn_pix = button::Button::new(30, 200, 110, 36, "PIX"); 
    let mut btn_vendas = button::Button::new(150, 200, 110, 36, "Vendas"); 
    let mut btn_previsao = button::Button::new(270, 200, 110, 36, "Previsão"); 
    let mut btn_recebimento = button::Button::new(390, 200, 110, 36, "Recebimento"); 
    let mut btn_ajustes = button::Button::new(510, 200, 110, 36, "Ajustes");  
 
    but_cal2.set_callback(move |_| {
        let cal = calendar::Calendar::default();
        let naive_date = cal.get_date();
        if let Some(naive_date) = naive_date {
            data_geracao_str.clear();
            data_geracao_str.push_str(naive_date.format("%Y-%m-%d").to_string().as_str());
            input2.set_value(data_geracao_str.as_str());
            data_geracao_str.push_str(" 00:00:00 +00:00");
 
            println!("{:?}",data_geracao_str);
 
        }
    });    
 
    wind.end();
    wind.show();
    app.run().unwrap();
 
}

Solution

  • You can .clone() the Button to get a second handle to the same button, which you can hand off to the first callback without losing it in the second.

    {
        let input1 = input1.clone();
        but_cal1.set_callback(move |_| {
            ...
            input1.set_value(data_geracao_inicio_str.as_str());
        });
    }
    
    // now you can still use input1 here
    

    This is a common pattern in Rust libraries; whenever you have a value that acts as a handle to some entity that can be interacted with externally (the button in the window), rather than only being used by its owner, it often implements the Clone trait in this way. Unfortunately, they don't always document this pattern clearly; fltk only mentions it in passing in its FAQ. You should keep an eye out for when Clone is available and see if it does what you want.