continued ui improvement

This commit is contained in:
core 2025-03-19 21:51:02 -05:00
parent 839de0bd5c
commit d53e294b7c
10 changed files with 220 additions and 40 deletions

View file

@ -94,7 +94,7 @@
}
}
</style>
<link rel="modulepreload" href="/wxbox-client-21f1a585bee166.js" crossorigin="anonymous" integrity="sha384-HYob1LR+vO//6cXv/O26ycz5UWAzGRoGIgqqjwGtEg7IyCm5vkgg1EMr8nvYobva"><link rel="preload" href="/wxbox-client-21f1a585bee166_bg.wasm" crossorigin="anonymous" integrity="sha384-qIpqnebYuFIyVLVlTpZyplFTfNmt4cw6Wgh1qG1FdgABRcHBhIkGKSsuM1/dLQB0" as="fetch" type="application/wasm"></head>
<link rel="modulepreload" href="/wxbox-client-96cce58fa4aaba7a.js" crossorigin="anonymous" integrity="sha384-rOwE8Z+dDRuQLsg/fUPw7V9/GJ3Oifopq6b88/pPM7xq2QmCD54SJdnx/SgS1/R1"><link rel="preload" href="/wxbox-client-96cce58fa4aaba7a_bg.wasm" crossorigin="anonymous" integrity="sha384-Rw805YQqcRKZ9iiDhDqyezvRhVu5nQt+IPPnlZCFQ+bPI7pIaxw5QmFJ4EuhBRVf" as="fetch" type="application/wasm"></head>
<body>
<!-- The WASM code will resize the canvas dynamically -->
@ -111,8 +111,8 @@
<script type="module">
import init, * as bindings from '/wxbox-client-21f1a585bee166.js';
const wasm = await init({ module_or_path: '/wxbox-client-21f1a585bee166_bg.wasm' });
import init, * as bindings from '/wxbox-client-96cce58fa4aaba7a.js';
const wasm = await init({ module_or_path: '/wxbox-client-96cce58fa4aaba7a_bg.wasm' });
window.wasmBindings = bindings;

View file

@ -198,7 +198,7 @@ function debugString(val) {
return className;
}
function __wbg_adapter_30(arg0, arg1, arg2) {
wasm.closure765_externref_shim(arg0, arg1, arg2);
wasm.closure791_externref_shim(arg0, arg1, arg2);
}
function takeFromExternrefTable0(idx) {
@ -214,7 +214,7 @@ function __wbg_adapter_35(arg0, arg1) {
}
function __wbg_adapter_38(arg0, arg1, arg2) {
wasm.closure1268_externref_shim(arg0, arg1, arg2);
wasm.closure1294_externref_shim(arg0, arg1, arg2);
}
/**
@ -1519,20 +1519,20 @@ function __wbg_get_imports() {
const ret = false;
return ret;
};
imports.wbg.__wbindgen_closure_wrapper2675 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 766, __wbg_adapter_30);
imports.wbg.__wbindgen_closure_wrapper2733 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 792, __wbg_adapter_30);
return ret;
};
imports.wbg.__wbindgen_closure_wrapper2677 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 766, __wbg_adapter_30);
imports.wbg.__wbindgen_closure_wrapper2735 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 792, __wbg_adapter_30);
return ret;
};
imports.wbg.__wbindgen_closure_wrapper2679 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 766, __wbg_adapter_35);
imports.wbg.__wbindgen_closure_wrapper2737 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 792, __wbg_adapter_35);
return ret;
};
imports.wbg.__wbindgen_closure_wrapper5044 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1269, __wbg_adapter_38);
imports.wbg.__wbindgen_closure_wrapper5102 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1295, __wbg_adapter_38);
return ret;
};
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {

View file

@ -19,7 +19,8 @@ pub struct App {
map: Map,
layer_selector: LayerSelector,
widget_gallery: WidgetGallery,
pub(crate) frame_time_history: History<f32>
pub(crate) frame_time_history: History<f32>,
add_layer_open: bool
}
impl App {
@ -49,6 +50,7 @@ impl App {
layer_selector: LayerSelector::default(),
widget_gallery: WidgetGallery::default(),
frame_time_history: History::new(1..100, 0.5),
add_layer_open: false
}
}
}
@ -65,7 +67,7 @@ impl eframe::App for App {
top_bar(ctx);
footer(ctx, &self);
left_bar(ctx);
left_bar(ctx, &mut self.add_layer_open, &mut self.map.layer_manager);
/*
egui::SidePanel::left("sidebar")

View file

@ -1,10 +1,13 @@
use std::convert::Into;
use std::sync::LazyLock;
use crate::map::tiles::LayerSource;
use crate::map::tiles::{LayerSource, LayerTypeHint};
pub static BASELAYER_OSM: LazyLock<LayerSource> = LazyLock::new(|| LayerSource {
source_id: 0x572dd260332d5f7f,
tile_url: "https://tile.openstreetmap.org/{z}/{x}/{y}.png".into(),
display_name: "OpenStreetMap (Base)".into()
display_name: "OpenStreetMap".into(),
type_hint: LayerTypeHint::Baselayer,
location: "Worldwide".into(),
source: "OpenStreetMap contributors".into()
});

View file

@ -1,35 +1,53 @@
use std::convert::Into;
use std::sync::LazyLock;
use crate::map::tiles::LayerSource;
use crate::map::tiles::{LayerSource, LayerTypeHint};
pub static NOAA_MRMS_MERGED_CREF_QC_CONUS: LazyLock<LayerSource> = LazyLock::new(|| LayerSource {
source_id: 0xC10FCD0566B7F952,
tile_url: format!("{}/grib2.noaa_mrms_merged_composite_reflectivity_qc_CONUS/{{z}}/{{x}}/{{y}}.png", env!("TILER_BASE_URL")),
display_name: "Merged Composite Reflectivity [CONUS-QCd] (NOAA MRMS)".into()
display_name: "Merged Composite Reflectivity QCd".into(),
type_hint: LayerTypeHint::RadarData,
location: "Continental US".into(),
source: "NOAA / MRMS".into()
});
pub static NOAA_MRMS_MERGED_CREF_QC_ALASKA: LazyLock<LayerSource> = LazyLock::new(|| LayerSource {
source_id: 0x779F656117545E91,
tile_url: format!("{}/grib2.noaa_mrms_merged_composite_reflectivity_qc_ALASKA/{{z}}/{{x}}/{{y}}.png", env!("TILER_BASE_URL")),
display_name: "Merged Composite Reflectivity [ALASKA-QCd] (NOAA MRMS)".into()
display_name: "Merged Composite Reflectivity QCd".into(),
type_hint: LayerTypeHint::RadarData,
location: "Alaska".into(),
source: "NOAA / MRMS".into()
});
pub static NOAA_MRMS_MERGED_CREF_QC_CARIB: LazyLock<LayerSource> = LazyLock::new(|| LayerSource {
source_id: 0xA7076E0145BC4BDD,
tile_url: format!("{}/grib2.noaa_mrms_merged_composite_reflectivity_qc_CARIB/{{z}}/{{x}}/{{y}}.png", env!("TILER_BASE_URL")),
display_name: "Merged Composite Reflectivity [CARIB-QCd] (NOAA MRMS)".into()
display_name: "Merged Composite Reflectivity QCd".into(),
type_hint: LayerTypeHint::RadarData,
location: "Caribbean".into(),
source: "NOAA / MRMS".into()
});
pub static NOAA_MRMS_MERGED_CREF_QC_GUAM: LazyLock<LayerSource> = LazyLock::new(|| LayerSource {
source_id: 0xB277C4B00469BD02,
tile_url: format!("{}/grib2.noaa_mrms_merged_composite_reflectivity_qc_GUAM/{{z}}/{{x}}/{{y}}.png", env!("TILER_BASE_URL")),
display_name: "Merged Composite Reflectivity [GUAM-QCd] (NOAA MRMS)".into()
display_name: "Merged Composite Reflectivity QCd".into(),
type_hint: LayerTypeHint::RadarData,
location: "Guam".into(),
source: "NOAA / MRMS".into()
});
pub static NOAA_MRMS_MERGED_CREF_QC_HAWAII: LazyLock<LayerSource> = LazyLock::new(|| LayerSource {
source_id: 0x238710F2CD275445,
tile_url: format!("{}/grib2.noaa_mrms_merged_composite_reflectivity_qc_HAWAII/{{z}}/{{x}}/{{y}}.png", env!("TILER_BASE_URL")),
display_name: "Merged Composite Reflectivity [HAWAII-QCd] (NOAA MRMS)".into()
display_name: "Merged Composite Reflectivity QCd".into(),
type_hint: LayerTypeHint::RadarData,
location: "Hawaii".into(),
source: "NOAA / MRMS".into()
});
pub static NOAA_MRMS_MERGED_RHOHV_3KM_CONUS: LazyLock<LayerSource> = LazyLock::new(|| LayerSource {
source_id: 0x0EFAF68CB6E30B8F,
tile_url: format!("{}/grib2.noaa_mrms_merged_rhohv_3km_CONUS/{{z}}/{{x}}/{{y}}.png", env!("TILER_BASE_URL")),
display_name: "Merged RhoHV @ 3km [CONUS] (NOAA MRMS)".into()
display_name: "Merged RhoHV @ 3km".into(),
type_hint: LayerTypeHint::RadarData,
location: "Continental US".into(),
source: "NOAA / MRMS".into()
});

View file

@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
use image::DynamicImage;
use poll_promise::Promise;
use serde::{Deserialize, Serialize};
@ -12,7 +13,7 @@ pub type XCoord = usize;
pub type YCoord = usize;
pub type LayerId = u64;
#[derive(Default, Serialize, Deserialize)]
#[derive(Default, Serialize, Deserialize, Debug)]
#[serde(default)]
pub struct LayerManager {
pub registered_layers: HashMap<LayerId, LayerSource>,
@ -79,13 +80,27 @@ impl LayerManager {
}
}
#[derive(Serialize, Deserialize, Clone)]
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct LayerSource {
pub source_id: u64,
pub tile_url: String,
pub display_name: String,
pub location: String,
pub source: String,
pub type_hint: LayerTypeHint
}
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
pub enum LayerTypeHint {
Baselayer,
RadarData,
}
pub struct Tile {
pub promise: Promise<Result<DynamicImage, String>>,
}
impl Debug for Tile {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", if self.promise.ready().is_some() { "<loaded texture>" } else { "<texture promise>" })
}
}

View file

@ -1,4 +1,6 @@
use std::any::Any;
use egui::emath::GuiRounding;
use egui::{emath, CursorIcon, Id, InnerResponse, LayerId, Order, Sense, Ui, UiBuilder};
pub mod layer_selector;
pub mod tokens;
@ -48,7 +50,6 @@ pub trait UiExt {
}
response
}
}
impl UiExt for egui::Ui {

View file

@ -1,9 +1,28 @@
use eframe::emath::Align;
use egui::{Color32, CursorIcon, FontFamily, Frame, Id, Layout, Response, RichText, ScrollArea, Theme, Ui, vec2, Visuals};
use egui::{Color32, CursorIcon, FontFamily, Frame, Id, Layout, Response, RichText, ScrollArea, Theme, Ui, vec2, Visuals, CornerRadius, Button, Margin, Label, Rect, Sense};
use egui::epaint::Marginf;
use egui::frame::Prepared;
use tracing::debug;
use crate::map::tiles::{LayerManager, LayerTypeHint};
use crate::ui::tokens::DESIGN_TOKENS;
use crate::ui::UiExt;
pub fn left_bar(ctx: &egui::Context) {
fn outer_rect(f: &Prepared) -> Rect {
let content_rect = f.content_ui.min_rect();
content_rect
+ f.frame.inner_margin
+ Marginf::from(f.frame.stroke.width)
+ f.frame.outer_margin
}
pub fn left_bar(ctx: &egui::Context, add_open: &mut bool, layer_manager: &mut LayerManager) {
let mut frame = Frame::side_top_panel(&ctx.style());
frame.inner_margin.top = 4;
@ -14,15 +33,135 @@ pub fn left_bar(ctx: &egui::Context) {
.frame(frame)
.show(ctx, |ui| {
pane_header(ui, "Layers", Some(egui_phosphor::regular::STACK), false, |ui| {
ui.button(RichText::new(egui_phosphor::regular::PLUS).size(12.0));
ui.style_mut().visuals.widgets.inactive.weak_bg_fill = Color32::TRANSPARENT;
if ui.button(RichText::new(egui_phosphor::regular::PLUS).size(12.0)).clicked() {
*add_open = true;
}
});
layer(ui, "Active Alerts", egui_phosphor::regular::TREE_STRUCTURE);
layer(ui, "Composite Reflectivity", egui_phosphor::regular::TARGET);
layer(ui, "TDWR Sites", egui_phosphor::regular::TREE_STRUCTURE);
layer(ui, "WSR-88D Sites", egui_phosphor::regular::TREE_STRUCTURE);
layer(ui, "OpenStreetMap", egui_phosphor::regular::MAP_TRIFOLD);
for (idx, layer) in layer_manager.active_layers.iter().enumerate() {
ui.dnd_drag_source(
Id::new(idx as u64 + layer),
idx,
|ui| {
if ui.button("hello").clicked() {
*add_open = true;
}
}
);
}
});
if *add_open {
let mut frame = Frame::popup(&ctx.style()).corner_radius(CornerRadius::ZERO);
frame.inner_margin.left = 0;
frame.inner_margin.right = 0;
egui::Modal::new(Id::new("add_source_modal"))
.frame(frame)
.show(ctx, |ui| {
pane_header(ui, "Add layer", Some(egui_phosphor::regular::STACK_PLUS), false, |ui| {
ui.style_mut().visuals.widgets.inactive.weak_bg_fill = Color32::TRANSPARENT;
if ui.button(RichText::new(egui_phosphor::regular::X).size(12.0)).clicked() {
*add_open = false;
}
});
for (id, registered_layer) in &layer_manager.registered_layers {
// ghost button
let mut frame = Frame::new();
frame.inner_margin.top = 4;
frame.inner_margin.left = 8;
frame.inner_margin.right = 8;
frame.inner_margin.bottom = 4;
let mut frame = frame.begin(ui);
{
frame.content_ui.horizontal(|ui| {
let mut frame = Frame::new()
.fill(DESIGN_TOKENS.get_color("colors.base.4", if ui.style().visuals.dark_mode { Theme::Dark } else { Theme::Light }).unwrap());
frame.inner_margin.top = 4;
frame.inner_margin.left = 8;
frame.inner_margin.right = 8;
frame.inner_margin.bottom = 4;
frame.corner_radius = CornerRadius::from(4);
frame.show(ui, |ui| {
let icon = match registered_layer.type_hint {
LayerTypeHint::Baselayer => egui_phosphor::regular::MAP_TRIFOLD,
LayerTypeHint::RadarData => egui_phosphor::regular::TARGET
};
ui.label(RichText::new(icon).size(24.0));
});
ui.vertical(|ui| {
ui.label(&registered_layer.display_name);
ui.horizontal(|ui| {
let type_hint = match registered_layer.type_hint {
LayerTypeHint::Baselayer => "Baselayer",
LayerTypeHint::RadarData => "Radar data",
};
let icon = match registered_layer.type_hint {
LayerTypeHint::Baselayer => egui_phosphor::regular::MAP_TRIFOLD,
LayerTypeHint::RadarData => egui_phosphor::regular::TARGET
};
let type_lbl = format!("{icon} {type_hint}");
ui.allocate_ui_with_layout(
vec2(90.0, 20.0),
Layout::left_to_right(Align::Center),
|ui| {
ui.label(RichText::new(type_lbl).weak());
ui.add_space(ui.available_width());
}
);
ui.allocate_ui_with_layout(
vec2(120.0, 20.0),
Layout::left_to_right(Align::Center),
|ui| {
ui.label(RichText::new(format!("{} {}", egui_phosphor::regular::NAVIGATION_ARROW, &registered_layer.location)).weak());
ui.add_space(ui.available_width());
}
);
ui.allocate_ui_with_layout(
vec2(100.0, 20.0),
Layout::left_to_right(Align::Center),
|ui| {
ui.label(RichText::new(format!("{} {}", egui_phosphor::regular::IDENTIFICATION_BADGE, &registered_layer.source)).weak());
ui.add_space(ui.available_width());
}
);
});
});
ui.add_space(ui.available_width());
});
}
let response = ui.allocate_rect(outer_rect(&frame), Sense::click_and_drag());
if response.hovered() {
frame.frame.fill = DESIGN_TOKENS.get_color("colors.base.7", if ui.style().visuals.dark_mode { Theme::Dark } else { Theme::Light }).unwrap();
ui.ctx().output_mut(|u| u.cursor_icon = CursorIcon::PointingHand);
}
if response.clicked() {
layer_manager.active_layers.push(*id);
debug!("{:?}", layer_manager);
*add_open = false;
}
frame.paint(ui);
}
});
}
}
fn pane_header(ui: &mut Ui, title: &str, icon: Option<&str>, top_separator: bool, add_contents: impl FnOnce(&mut Ui)) {
@ -57,8 +196,9 @@ fn pane_header(ui: &mut Ui, title: &str, icon: Option<&str>, top_separator: bool
ui.full_span_separator();
}
/*
fn layer(ui: &mut Ui, title: &str, icon: &str) {
let response = ui.dnd_drag_source(Id::new(title), "test", |ui| {
ui.passthrough_dnd_drag_source(Id::new(title), title.to_owned(), |ui| {
let mut frame = Frame::new();
//frame.fill = ui.style().visuals.hyperlink_color;
frame.inner_margin.left = 8;
@ -99,11 +239,12 @@ fn layer(ui: &mut Ui, title: &str, icon: &str) {
}
let response = frame.allocate_space(ui);
if response.hovered() {
frame.frame.fill = DESIGN_TOKENS.get_color("colors.base.7", if ui.style().visuals.dark_mode { Theme::Dark } else { Theme::Light }).unwrap();
frame.frame.fill = ;
ui.ctx().output_mut(|u| u.cursor_icon = CursorIcon::Grab);
}
frame.paint(ui);
}).response;
});
}
}
*/

View file

@ -1,7 +1,7 @@
use std::sync::LazyLock;
use egui::{Color32, FontData, FontFamily, Stroke, Style, Theme, Vec2};
use egui::{Color32, CornerRadius, FontData, FontFamily, Stroke, Style, Theme, Vec2};
use egui::epaint::text::{FontInsert, FontPriority, InsertFontFamily};
use egui::style::Selection;
use serde::{Deserialize, Serialize};