Iced + impl Program for MyApp + canvas::Program: Unable to setup app program

In my Iced programs, normally I have 1 state variable "State" which contains the data. I then use "impl State" to assign logic functions such as update and view. I want to attempt to plot some numbers on a canvas so I crated a simple Iced program that created a canvas and allowed the radius of the circle to changed. It worked. Now I am trying to modify this program so that the canvas has 1 structure containing its data and the app has 1 structure containing its data. In addition, I created 2 additional empty structures to hold the logic for the canvas and app. I attempt to pull this all off by creating a program with "impl Program for MyApp" but have hit a wall. There are a couple of issues that I have notated in the code. If someone could help point me in the right direction it will be greatly appreciated.

use iced::alignment::Horizontal;
use iced::widget::{button, canvas, column, text};  
use iced::{Color, Element, Length, Rectangle, Renderer, Size, Task, Theme, mouse};  
use iced::widget::row;

use iced::Program;

#[derive(Debug, Clone)]  
enum ChangeSize {
    IncSize,
    DecSize,
}

#[derive(Debug, Clone)]  
enum CanvasMessage {  
    IncreaseRadius,  
    DecreaseRadius,  
}  

enum Screen {  
    Main,  
    Canvas(CanvasState),  
}  
#[derive(Debug, Clone)]  
enum Message {  
    ShowCanvas,  
    BackToMain,  
    Canvas(ChangeSize),   
}  
struct AppState {
    screen: Screen,
    canvas_state: CanvasState,
}
struct MyApp {}

#[derive(Default)]
struct CanvasState {
    circle_radius: f32,
}

struct MyCanvas {}

impl<Message> canvas::Program<Message> for MyCanvas {  

    type State = CanvasState;  
  
    fn draw(  
        &self,  
        state: &CanvasState,  
        renderer: &Renderer,  
        _theme: &Theme,  
        bounds: Rectangle,  
        _cursor: mouse::Cursor  
    ) -> Vec<canvas::Geometry> {  

        let mut frame = canvas::Frame::new(renderer, bounds.size());  
        let circle = canvas::Path::circle(frame.center(), state.circle_radius);  
        frame.fill(&circle, Color::BLACK);  
        vec![frame.into_geometry()]  
    }  
}  

impl Program for MyApp {

    type State = AppState;
    type Message = Message;
    type Theme = Theme;
    type Renderer = Renderer;
    type Executor = Default;  
// determine default executor

    fn window(&self) { 
// determine how to indicate default
    }

    fn settings(&self) -> iced::Settings {
        iced::Settings::default()
    }

    fn name() -> &'static str {
        let program_name = "Canvas";
        &program_name
    }

    fn boot(&self) -> (Self::State, iced::Task<Self::Message>) {
        let initial_state = Self::State {
            screen: Screen::Main,
            canvas_state: CanvasState { circle_radius: 25.0 }
        };

        (initial_state, Task::none())
    }

    fn update(&self, state: &mut Self::State , message: Message) -> Task<Message> {    
        match message {  
            Message::ShowCanvas => {  
                state.screen = Screen::Canvas(CanvasState { circle_radius: state.canvas_state.circle_radius });
                Task::none()  
            }  
            Message::BackToMain => {  
                state.screen = Screen::Main;  
                Task::none()  
            }
            Message::Canvas(msg) => {
                match msg {
                    ChangeSize::DecSize => {
                        state.canvas_state.circle_radius -= 10.0;         
                    }
                    ChangeSize::IncSize => {
                        state.canvas_state.circle_radius += 10.0;                     
                    }
                }
                state.screen = Screen::Canvas(CanvasState { circle_radius: state.canvas_state.circle_radius });
                Task::none()  
            }
        }  
    }  

    fn view(&self, state: &'a Self::State, app_id: iced::window::Id) -> Element<'_, Message> {
// 'a appears to be a problem
        match &state.screen {  
            Screen::Main => {  
                column![  
                    text("Main Screen"),  
                    button("Show Canvas").on_press(Message::ShowCanvas)  
                ]  
                .into()  
            }  
            Screen::Canvas(canvas_program) => {  
                column![  
                    button("Back").on_press(Message::BackToMain),  

                    canvas(canvas_program.clone()) 
// the trait iced::widget::canvas::Program not implemented for CanvasState
                        .width(Length::Fill)  
                        .height(Length::Fill), 

                    row![
                        button("Decrease").on_press(Message::Canvas(ChangeSize::DecSize)),  
                        button("Increase").on_press(Message::Canvas(ChangeSize::IncSize)),  
                    ]
                    .spacing(100)
                ]  
                .align_x(Horizontal::Center)
                .spacing(100)
                .width(Length::Fill)
                .into()  
            }  
        }  
    }

}

fn main() -> iced::Result {  


}

Without seeing the full error messages, I can't be sure of what's going on, but I am slightly suspicious of this line. If you try to clone &T where T: !Clone, the method-call syntax sugar would apply an "autoref". In this case, I think that canvas_program.clone() refers to <&CanvasProgram as Clone>::clone(&canvas_program)... which clones the &CanvasProgram reference, not the CanvasProgram.

Looks like you didn't derive Clone for CanvasState? (I'd recommend derive(Debug, Default, Clone, Copy) on CanvasState. There are clippy lints for missing Debug and Copy implementations - generally, almost every type should be Debug, and most types which could be Copy should be Copy.)

Think of lifetime names (other than '_ or 'static) like 'a as variables. You need to introduce/declare a variable before you use it. Lifetime parameter names are declared as generic parameters, like fn view<'a>(..) (i.e., it would be part of the function signature)... but traits define the exact function signatures of their methods. You should copy the exact signature of the trait method, including lifetimes. Looking at iced v0.14.0's docs, I think it's something like the following:

    fn view<'a>(
        &self,
        state: &'a Self::State,
        window: Id,
    ) -> Element<'a, Self::Message, Self::Theme, Self::Renderer>;

Warning: I have not used iced before, so I cannot give big-picture help.

you are supposed to pass an argument of type impl canvas::Program, not the associated canvas::Program::State. I didn't read all your code, but it seems the type MyCanvas fits here, try:

canvas(MyCanvas{})
    .width(Length::Fill)
    .height(Length::Fill)

as for the lifetime:

just copy the exact signature of the method in the trait definition, your signature is wrong.

Thank you for the responses. I think I have it worked out. Now for one follow up question.
What line of code do I place in the main function to run the program. In previous programs, applications, I used iced::application .....
Does not seem to work here. Also tried MyApp::run() and that does not work. Any help will be appreciated.

are you studying the inner working of iced?

typically an application does not need to implement the Program directly, the Application wrapper is what most applications should use.

the Program trait is intended for advanced users, e.g., in case you want to write a port (sometimes referred to as "backend" or "windowing system") to a new platform.

the default backend of iced is iced_winit. specifically, you use iced_winit::run() to run the your own Program:

After additional reading and your input, I have realized that using Program was an error on my part. I just did not understand that it is not meant for this type of application. It is now clear to me that I should rewrite the code as an Application. Thank you all for the input.