Canvas

Technically, the canvas is a built-in control. Nevertheless, its way to handle resources is very similar to a Ui.

Canvas is a light wrapper over the Direct2D api. As of BETA1, only a few functions have been implemented. More will be added in the BETA2 release. The Canvas control is planned to wrap the whole Direct2D API.

For a concrete example, see the canvas example.

Creation

A canvas can be added to an existing Ui using the template CanvasT or using the nwg_canvas! macro. The template do not have any particular properties:
pub struct CanvasT<ID: Hash+Clone> {
    pub parent: ID,
    pub position: (i32, i32),
    pub size: (u32, u32),
    pub visible: bool,
    pub disabled: bool,
}
The canvas control accept a wide range of events, enabling it to respond easily to any user input: Event::Destroyed, Event::KeyDown, Event::KeyUp, Event::Char, Event::MouseDown, Event::MouseUp, Event::Moved, Event::Resized, Event::Paint, Event::Raw

Resources creation

Just like a Ui needs to be packed with controls and resources, a canvas needs to be packed with brushes, pen and other drawing utilities.

Canvas has a set of methods like create_solid_brush that creates a named resource in the canvas. Then, this resource can be used in the painting phase. Those functions take a ID using the same type as the UI and a struct defined under the nwg::constants module.
let mut canvas = nwg_get_mut!(app; ("Canvas", nwg::Canvas<&'static str>));

let b1 = nwgc::SolidBrush{color:(0.0, 0.7, 1.0, 1.0)};
let b2 = nwgc::SolidBrush{color:(0.0, 1.0, 0.5, 1.0)};
let b3 = nwgc::SolidBrush{color:(1.0, 1.0, 0.0, 1.0)};
let p1 = nwgc::Pen {
    start_cap: nwgc::CapStyle::Round,
    end_cap: nwgc::CapStyle::Round,
    dash_cap: nwgc::CapStyle::Round,
    line_join: nwgc::LineJoin::Round,
    miter_limit: 0.0,
    dash_style: nwgc::DashStyle::Dash,
    dash_offset: 5.0
 };

canvas.create_solid_brush(&"SolidBrush1", &b1).expect("Failed to create brush 1");
canvas.create_solid_brush(&"SolidBrush2", &b2).expect("Failed to create brush 2");
canvas.create_solid_brush(&"SolidBrush3", &b3).expect("Failed to create brush 3");
canvas.create_pen(&"DashedPen", &p1).expect("Failed to create pen");

Painting

Painting is the action of drawing shapes and stuff on a canvas. It should only be done during a Paint event.

To begin drawing into a canvas, a CanvasRenderer object must be requested using the canvas.renderer() method. Under very rare circumstances, the renderer function can fail.

Once the renderer is acquired, functions like clear, get_render_size or set_transform can be used to prepare the renderer settings when drawing stuff.

Finally, methods like draw_* and fill_* can be used to draw the outline or fill a shape.
("Canvas", "Paint", Event::Paint, |app, _, _, _| {
    let mut canvas = nwg_get_mut!(app; ("Canvas", nwg::Canvas<&'static str>));

    // Get the renderer and clear the last scene
    let mut renderer = canvas.renderer().unwrap();
    renderer.clear(0.3, 0.3, 0.6, 1.0);
            
    // Drawing setup
    let (w, h) = renderer.get_render_size();
    renderer.set_transform( &[[1.0, 0.0], [0.0, 1.0], [w/2.0, h/2.0]] );

    let r1 = nwgc::Rectangle{left: -50.0, right: 50.0, top: -50.0, bottom: 50.0};
    let r2 = nwgc::Rectangle{left: -100.0, right: 100.0, top: -100.0, bottom: 100.0};
    let r3 = nwgc::Rectangle{left: -200.0, right: 200.0, top: -200.0, bottom: 200.0};
    let e1 = nwgc::Ellipse{ center: (0.0, 0.0), radius: (25.0, 25.0) };
    let e2 = nwgc::Ellipse{ center: (0.0, 0.0), radius: (190.0, 190.0) };

    // Draw the shapes
    renderer.draw_ellipse(&"SolidBrush2", Some(&"DashedPen"), &e2, 6.0).unwrap();
    renderer.draw_rectangle(&"SolidBrush3", None, &r3, 3.0).unwrap();
    renderer.fill_rectangle(&"SolidBrush2", &r2).unwrap();
    renderer.fill_rounded_rectangle(&"SolidBrush1", &r1, (15.0, 15.0)).unwrap();
    renderer.fill_ellipse(&"SolidBrush3", &e1).unwrap();
}),

Other methods

The canvas control has a few other methods not directly related to painting.

redraw

Force the canvas to redraw itself. Don't call this while handling the Paint event.
canvas.redraw()

get_dpi / set_dpi

Get or set the dot per inch of the canvas so that the painted result look consistently good across a wide variety of high-DPI display settings. For more information see:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd756649(v=vs.85).aspx
canvas.set_dpi(100.0, 100.0);
let (dpi_x, dpi_y) = canvas.get_dpi();

set_render_size

Calling canvas.set_size resize the window control, but not the underlying render target of the canvas. If the control size do not match the render size, the painted image will be downscaled or upscaled. In order to set the render_size, set_render_size can be used. For a detailed example of what happens see:
https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
let mut canvas = nwg_get_mut!(app; ("Canvas", nwg::Canvas<&'static str>));
canvas.set_size(w, h);
canvas.set_render_size(w, h);