mod font; use crate::font::Font; // this brings in the struct Font use gtk::cairo::Context; use gtk::prelude::*; use gtk::{ Application, ApplicationWindow, DrawingArea, HeaderBar, Label, ListBox, ListBoxRow, MenuButton, Popover, }; fn main() { let app = Application::builder() .application_id("com.example.DotMatrix") .build(); app.connect_activate(build_ui); app.run(); } fn build_ui(app: >k::Application) { let window = ApplicationWindow::builder() .application(app) .title("Dot Matrix") .default_width(1000) .default_height(800) .build(); // HeaderBar let header_bar = HeaderBar::new(); window.set_titlebar(Some(&header_bar)); // MenuButton let menu_button = MenuButton::new(); menu_button.set_icon_name("open-menu-symbolic"); header_bar.pack_start(&menu_button); // Popover let popover = Popover::new(); popover.set_parent(&menu_button); menu_button.set_popover(Some(&popover)); // ListBox in popover let list_box = ListBox::new(); list_box.set_selection_mode(gtk::SelectionMode::None); // No selection on menu items // Add menu items (ListBoxRows with Labels) let item1_row = ListBoxRow::new(); let item1_label = Label::new(Some("Settings")); item1_row.set_child(Some(&item1_label)); list_box.append(&item1_row); let item2_row = ListBoxRow::new(); let item2_label = Label::new(Some("Help")); item2_row.set_child(Some(&item2_label)); list_box.append(&item2_row); let item3_row = ListBoxRow::new(); let item3_label = Label::new(Some("About")); item3_row.set_child(Some(&item3_label)); list_box.append(&item3_row); popover.set_child(Some(&list_box)); // Set the ListBox as the child of the Popover let drawing_area = DrawingArea::new(); let rows = 100 as u8; let cols = 100 as u8; // Generate the matrix using iterators let mut dot_matrix: Vec> = (0..rows).map(|_| (0..cols).map(|_| 0).collect()).collect(); let insert_matrix: Vec> = (0..7).map(|_| (0..5).map(|_| 1).collect()).collect(); let font_5x7: Font = Font::new("5x7"); let char_bitmap = font_5x7.get_char_bitmap(1).unwrap(); insert_matrix_at(&mut dot_matrix, &insert_matrix, 0, 0); insert_matrix_at(&mut dot_matrix, &insert_matrix, 0, 6); insert_matrix_at(&mut dot_matrix, &char_bitmap, 0, 12); drawing_area.set_draw_func(move |_area, cr, width, height| { draw_dot_matrix(cr, width, height, &dot_matrix); }); window.set_child(Some(&drawing_area)); window.show(); } fn draw_dot_matrix(cr: &Context, width: i32, height: i32, matrix: &Vec>) { // let rows = matrix.len(); // let _cols = if rows > 0 { matrix[0].len() } else { 0 }; // Background: dark gray cr.set_source_rgb(0.1, 0.1, 0.1); cr.rectangle(0.0, 0.0, width as f64, height as f64); let _ = cr.fill(); // Set dot color (yellow) cr.set_source_rgb(1.0, 1.0, 0.0); // Calculate spacing let spacing_x = 25.0; let spacing_y = 25.0; let radius = 10.0; for (row_index, row) in matrix.iter().enumerate() { for (col_index, &val) in row.iter().enumerate() { if val == 1 { let x = (col_index as f64 + 0.5) * spacing_x; let y = (row_index as f64 + 0.5) * spacing_y; cr.arc(x, y, radius, 0.0, std::f64::consts::PI * 2.0); let _ = cr.fill(); } } } } fn insert_matrix_at( target: &mut Vec>, insert: &Vec>, row_offset: usize, col_offset: usize, ) { for (i, insert_row) in insert.iter().enumerate() { for (j, &val) in insert_row.iter().enumerate() { if row_offset + i < target.len() && col_offset + j < target[0].len() { target[row_offset + i][col_offset + j] = val; } } } }