plotters-wxdragon 0.1.1

Plotters backend for wxDragon, allowing drawing Plotters graphs on wxWidgets device contexts.
Documentation

plotters-wxdragon

plotters-wxdragon is a backend for Plotters, to draw plots in a GUI window managed by wxDragon.

wxDragon is a binding of wxWidgets for rust. wxWidgets is a cross-platform GUI library toolkit for desktop applications, that uses the native GUI toolkit on Windows, macOS, and Linux.

Plotters is a Rust drawing library focusing on data plotting for both WASM and native applications.

Examples of bitmaps produced with this backend:

3D Plot Chart Plot Mandelbrot Plot

Getting started

Quick start

  1. Follow wxDragon instructions to install the wxdragon crate. You will need the wxWidgets library for your OS so be sure to follow the instructions.

  2. Clone this repository and run the x2 plotting example to check that it works for you.

    git clone https://github.com/threefold3/plotters-wxdragon.git
    cd plotters-wxdragon
    cargo run --example x2
    

    This will open a new window displaying a simple y=x^2 plot.

Integrating with a project

  1. Add the following to your Cargo.toml file:

    [dependencies]
    wxdragon = "0.9"
    plotters = "0.3"
    plotters-wxdragon = "0.1"
    
  2. Create an app with a wxdragon::Panel, and use the panel's on_paint handler to create a new wxdragon::AutoBufferedPaintDC (device context) each time, wrap it in a WxBackend and then draw on it.

    use plotters::prelude::*;
    use plotters::style::text_anchor::{HPos, Pos, VPos};
    use plotters_wxdragon::WxBackend;
    use wxdragon::{self as wx, WindowEvents, WxWidget};
    
    struct DrawingPanel {
        panel: wx::Panel,
    }
    
    impl DrawingPanel {
        fn new(parent: &wx::Frame) -> Self {
            let panel = wx::PanelBuilder::new(parent).build();
            panel.set_background_style(wx::BackgroundStyle::Paint);
    
            // Register the paint handler with a move closure
            panel.on_paint(move |_event| {
                // Create a device context (wxdragon has several types)
                // and a plotters backend
                let dc = wx::AutoBufferedPaintDC::new(&panel);
                let mut backend = WxBackend::new(&dc);
    
                // Create a plotters plot as you would with any other backend
                backend
                    .draw_rect((300, 250), (500, 350), &BLACK, false)
                    .unwrap();
                let style = TextStyle::from(("monospace", 32.0).into_font())
                    .pos(Pos::new(HPos::Center, VPos::Center));
                backend
                    .draw_text("hello, world", &style, (400, 300))
                    .unwrap();
    
                // Call present() when you are ready
                backend.present().expect("present");
            });
    
            // Handle SIZE events to refresh when the window size changes
            panel.on_size(move |_event| {
                panel.refresh(true, None);
            });
    
            Self { panel }
        }
    }
    
    impl std::ops::Deref for DrawingPanel {
        type Target = wx::Panel;
    
        fn deref(&self) -> &Self::Target {
            &self.panel
        }
    }
    
    fn main() {
        let _ = wxdragon::main(|_| {
            let frame = wx::Frame::builder()
                .with_title("Getting started")
                // with this, wx produces a canvas of size 800 x 600
                .with_size(wx::Size::new(852, 689))
                .build();
    
            let drawing_panel = DrawingPanel::new(&frame);
    
            // Initial paint
            drawing_panel.refresh(true, None);
    
            frame.show(true);
        });
    }
    

    You can find more details in the examples for how to integrate a plot in your wxWidgets application:

    • x2: simple y=x^2 plot in a wxWidgets frame
    • text: a single window that shows various text orientations and a toolbar that can modify application state

    There are also more tests, that illustrate that most existing plotters examples work without change. In these tests we write to to an in-memory device context instead of a device context linked to a Panel, and compare to a reference png images to ensure non-regression.

How this works

This crate implements a backend for Plotters. It uses the existing drawing context of wxWidgets, and maps plotters drawing primitives to corresponding calls fo the wxWidgets API.

See also plotters-backend for reference on implementing a backend for plotters.

Roadmap

This project is in its early stages. Future plans include:

  • Canvas interaction with the mouse (zoom/pan).
  • Canvas interaction with toolbar buttons (zoom/pan/reset/select).
  • Test the blit_bitmap function (no working example found yet).
  • Performance benchmark.
  • Make default font size more consistent with Plotters.
  • Find a way to use wxGLCanvas for hardware acceleration?

License

This project is dual-licensed under Apache 2.0 and MIT terms.

Contributions

Unless explicitly stated otherwise, contributions to this project, as defined in the Apache 2.0 license, are dual-licensed under Apache 2.0 and MIT. You do not need to explicitly state this when contributing. To opt out, please explicitly state "Not a Contribution" with your submission.

This project follows the following guidelines:

  • Format the code with cargo fmt.
  • For any changes in markdown files, use rumdl fmt.
  • Lint your code with cargo check, cargo test, cargo clippy, and cargo doc.
  • Use conventional commits.