egui-map-view 0.6.2

An slippy map viewer for egui applications.
Documentation
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
#![allow(rustdoc::missing_crate_level_docs)] // it's an example

use eframe::egui;
use egui::UiKind;
use egui_map_view::{
    Map,
    config::OpenStreetMapConfig,
    layers::text::{TextLayer, TextLayerMode, TextSize},
};

fn main() -> eframe::Result {
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default().with_inner_size([800.0, 600.0]),
        ..Default::default()
    };

    eframe::run_native(
        "Place text on map",
        options,
        Box::new(|_cc| Ok(Box::<MyApp>::default())),
    )
}

struct MyApp {
    map: Map,
}

impl Default for MyApp {
    fn default() -> Self {
        let mut map = Map::new(OpenStreetMapConfig::default());
        map.add_layer("text_layer", TextLayer::default());

        Self { map }
    }
}

impl eframe::App for MyApp {
    fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default()
            .frame(egui::Frame::NONE)
            .show_inside(ui, |ui| {
                ui.add_sized(ui.available_size_before_wrap(), &mut self.map);
            });

        // Show the main controls window.
        egui::Window::new("Controls")
            .resizable(false)
            .default_width(280.0)
            .show(ui.ctx(), |ui| {
                if let Some(layer) = self.map.layer_mut::<TextLayer>("text_layer") {
                    ui.heading("Mode");
                    ui.horizontal(|ui| {
                        ui.radio_value(&mut layer.mode, TextLayerMode::Disabled, "Disabled");
                        ui.radio_value(&mut layer.mode, TextLayerMode::Modify, "Modify");
                    });
                }
            });

        // Show the edit window if we are adding or modifying a text element.
        if let Some(layer) = self.map.layer_mut::<TextLayer>("text_layer") {
            // Take the editing state out of the layer to modify it.
            if let Some(mut editing) = layer.editing.take() {
                let mut open = true;
                let mut should_commit = false;
                let title = if editing.index.is_some() {
                    "Edit Text"
                } else {
                    "Add Text"
                };
                egui::Window::new(title)
                    .open(&mut open)
                    .resizable(false)
                    .show(ui.ctx(), |ui| {
                        ui.text_edit_singleline(&mut editing.properties.text);

                        ui.horizontal(|ui| {
                            ui.label("Text Color:");
                            ui.color_edit_button_srgba(&mut editing.properties.color);
                        });

                        ui.horizontal(|ui| {
                            ui.label("Background Color:");
                            ui.color_edit_button_srgba(&mut editing.properties.background);
                        });

                        ui.label("Text Size");
                        let is_static = matches!(editing.properties.size, TextSize::Static(_));
                        if ui.radio(is_static, "Static").clicked() {
                            editing.properties.size = TextSize::Static(12.0);
                        }
                        if let TextSize::Static(size) = &mut editing.properties.size {
                            ui.add_enabled(is_static, egui::Slider::new(size, 4.0..=50.0));
                        }

                        let is_relative = matches!(editing.properties.size, TextSize::Relative(_));
                        if ui.radio(is_relative, "Relative").clicked() {
                            editing.properties.size = TextSize::Relative(5000.0);
                        }
                        if let TextSize::Relative(size) = &mut editing.properties.size {
                            ui.add_enabled(
                                is_relative,
                                egui::Slider::new(size, 100.0..=10000.0)
                                    .logarithmic(true)
                                    .text("meters"),
                            );
                        }

                        ui.separator();
                        ui.horizontal(|ui| {
                            if ui.button("Ok").clicked() {
                                should_commit = true;
                                ui.close_kind(UiKind::Window);
                            }
                            if ui.button("Cancel").clicked() {
                                should_commit = false;
                                ui.close_kind(UiKind::Window);
                            }
                        });
                    });

                if should_commit {
                    layer.editing = Some(editing);
                    layer.commit_edit();
                } else if open {
                    // If the window is still open, put the editing state back for the next frame.
                    layer.editing = Some(editing);
                }
            }
        }
    }
}