egui: allocate whole available height for canvas

This commit is contained in:
Mikolaj Wielgus 2024-09-10 22:54:44 +02:00
parent 0cdec86900
commit 8c671e5a2c
5 changed files with 29 additions and 47 deletions

View File

@ -202,7 +202,7 @@ impl eframe::App for App {
ctx, ctx,
&self.translator, &self.translator,
&self.viewport, &self.viewport,
viewport_rect, &viewport_rect,
&self.maybe_execute, &self.maybe_execute,
); );

View File

@ -14,14 +14,13 @@ impl Bottom {
ctx: &egui::Context, ctx: &egui::Context,
tr: &Translator, tr: &Translator,
viewport: &Viewport, viewport: &Viewport,
viewport_rect: egui::Rect, viewport_rect: &egui::Rect,
maybe_execute: &Option<ExecuteWithStatus>, maybe_execute: &Option<ExecuteWithStatus>,
) { ) {
egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| { egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| {
let transform = egui::emath::RectTransform::from_to(viewport.from_rect, viewport_rect); let latest_pos = viewport.transform.inverse()
let latest_pos = transform * ctx.input(|i| i.pointer.latest_pos().unwrap_or_default())
.inverse() - viewport_rect.size() / 2.0;
.transform_pos(ctx.input(|i| i.pointer.latest_pos().unwrap_or_default()));
let mut message = String::from(""); let mut message = String::from("");

View File

@ -6,14 +6,14 @@ use topola::{
pub struct Painter<'a> { pub struct Painter<'a> {
ui: &'a mut egui::Ui, ui: &'a mut egui::Ui,
transform: egui::emath::RectTransform, transform: egui::emath::TSTransform,
paint_bboxes: bool, paint_bboxes: bool,
} }
impl<'a> Painter<'a> { impl<'a> Painter<'a> {
pub fn new( pub fn new(
ui: &'a mut egui::Ui, ui: &'a mut egui::Ui,
transform: egui::emath::RectTransform, transform: egui::emath::TSTransform,
paint_bboxes: bool, paint_bboxes: bool,
) -> Self { ) -> Self {
Self { Self {
@ -29,11 +29,11 @@ impl<'a> Painter<'a> {
PrimitiveShape::Seg(seg) => egui::Shape::line_segment( PrimitiveShape::Seg(seg) => egui::Shape::line_segment(
[ [
self.transform self.transform
.transform_pos([seg.from.x() as f32, -seg.from.y() as f32].into()), .mul_pos([seg.from.x() as f32, -seg.from.y() as f32].into()),
self.transform self.transform
.transform_pos([seg.to.x() as f32, -seg.to.y() as f32].into()), .mul_pos([seg.to.x() as f32, -seg.to.y() as f32].into()),
], ],
egui::Stroke::new(seg.width as f32 * self.transform.scale().x, color), egui::Stroke::new(seg.width as f32 * self.transform.scaling, color),
), ),
PrimitiveShape::Bend(bend) => { PrimitiveShape::Bend(bend) => {
let circle = bend.circle(); let circle = bend.circle();
@ -46,12 +46,12 @@ impl<'a> Painter<'a> {
for i in 0..=100 { for i in 0..=100 {
let x = circle.pos.x() + circle.r * (angle_from + i as f64 * angle_step).cos(); let x = circle.pos.x() + circle.r * (angle_from + i as f64 * angle_step).cos();
let y = circle.pos.y() + circle.r * (angle_from + i as f64 * angle_step).sin(); let y = circle.pos.y() + circle.r * (angle_from + i as f64 * angle_step).sin();
points.push(self.transform.transform_pos([x as f32, -y as f32].into())); points.push(self.transform.mul_pos([x as f32, -y as f32].into()));
} }
egui::Shape::line( egui::Shape::line(
points, points,
egui::Stroke::new(bend.width as f32 * self.transform.scale().x, color), egui::Stroke::new(bend.width as f32 * self.transform.scaling, color),
) )
} }
}; };
@ -65,7 +65,7 @@ impl<'a> Painter<'a> {
max: [bbox.upper()[0] as f32, -bbox.lower()[1] as f32].into(), max: [bbox.upper()[0] as f32, -bbox.lower()[1] as f32].into(),
}; };
self.ui.painter().add(egui::Shape::rect_stroke( self.ui.painter().add(egui::Shape::rect_stroke(
self.transform.transform_rect(rect), self.transform.mul_rect(rect),
egui::Rounding::ZERO, egui::Rounding::ZERO,
egui::Stroke::new(1.0, egui::Color32::GRAY), egui::Stroke::new(1.0, egui::Color32::GRAY),
)); ));
@ -80,8 +80,8 @@ impl<'a> Painter<'a> {
fn dot_shape(&mut self, circle: Circle, color: egui::epaint::Color32) -> egui::Shape { fn dot_shape(&mut self, circle: Circle, color: egui::epaint::Color32) -> egui::Shape {
egui::Shape::circle_filled( egui::Shape::circle_filled(
self.transform self.transform
.transform_pos([circle.pos.x() as f32, -circle.pos.y() as f32].into()), .mul_pos([circle.pos.x() as f32, -circle.pos.y() as f32].into()),
circle.r as f32 * self.transform.scale().x, circle.r as f32 * self.transform.scaling,
color, color,
) )
} }
@ -92,7 +92,7 @@ impl<'a> Painter<'a> {
.exterior_coords_iter() .exterior_coords_iter()
.map(|coords| { .map(|coords| {
self.transform self.transform
.transform_pos([coords.x as f32, -coords.y as f32].into()) .mul_pos([coords.x as f32, -coords.y as f32].into())
}) })
.collect(), .collect(),
color, color,
@ -104,9 +104,9 @@ impl<'a> Painter<'a> {
self.ui.painter().add(egui::Shape::line_segment( self.ui.painter().add(egui::Shape::line_segment(
[ [
self.transform self.transform
.transform_pos([from.x() as f32, -from.y() as f32].into()), .mul_pos([from.x() as f32, -from.y() as f32].into()),
self.transform self.transform
.transform_pos([to.x() as f32, -to.y() as f32].into()), .mul_pos([to.x() as f32, -to.y() as f32].into()),
], ],
stroke, stroke,
)); ));

View File

@ -22,13 +22,14 @@ use topola::{
use crate::{app::execute, layers::Layers, overlay::Overlay, painter::Painter, top::Top}; use crate::{app::execute, layers::Layers, overlay::Overlay, painter::Painter, top::Top};
pub struct Viewport { pub struct Viewport {
pub from_rect: egui::emath::Rect, pub transform: egui::emath::TSTransform,
} }
impl Viewport { impl Viewport {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
from_rect: egui::Rect::from_x_y_ranges(0.0..=1000000.0, 0.0..=500000.0), //from_rect: egui::Rect::from_x_y_ranges(0.0..=1000000.0, 0.0..=500000.0),
transform: egui::emath::TSTransform::new([0.0, 0.0].into(), 0.01),
} }
} }
@ -45,32 +46,16 @@ impl Viewport {
egui::Frame::canvas(ui.style()).show(ui, |ui| { egui::Frame::canvas(ui.style()).show(ui, |ui| {
ui.ctx().request_repaint(); ui.ctx().request_repaint();
let desired_size = ui.available_width() * egui::vec2(1.0, 0.5); let (_id, viewport_rect) = ui.allocate_space(ui.available_size());
let (_id, viewport_rect) = ui.allocate_space(desired_size); let latest_pos = self.transform.inverse() * (ctx.input(|i| i.pointer.latest_pos().unwrap_or_default()));
let old_transform = let old_scaling = self.transform.scaling;
egui::emath::RectTransform::from_to(self.from_rect, viewport_rect); self.transform.scaling *= ctx.input(|i| i.zoom_delta());
let latest_pos = old_transform
.inverse()
.transform_pos(ctx.input(|i| i.pointer.latest_pos().unwrap_or_default()));
let old_scale = old_transform.scale().x; self.transform.translation += latest_pos.to_vec2() * (old_scaling - self.transform.scaling);
self.from_rect = self.from_rect / ctx.input(|i| i.zoom_delta()); self.transform.translation += ctx.input(|i| i.smooth_scroll_delta);
let new_scale = egui::emath::RectTransform::from_to(self.from_rect, viewport_rect) let mut painter = Painter::new(ui, self.transform, top.show_bboxes);
.scale()
.x;
self.from_rect = self.from_rect.translate(
ctx.input(|i| latest_pos.to_vec2() * (new_scale - old_scale) / new_scale),
);
self.from_rect = self
.from_rect
.translate(ctx.input(|i| -i.raw_scroll_delta / new_scale));
let transform = egui::emath::RectTransform::from_to(self.from_rect, viewport_rect);
let mut painter = Painter::new(ui, transform, top.show_bboxes);
if let Some(ref mut invoker) = maybe_invoker { if let Some(ref mut invoker) = maybe_invoker {
if ctx.input(|i| i.pointer.any_click()) { if ctx.input(|i| i.pointer.any_click()) {

View File

@ -1,5 +1,3 @@
use std::convert::Infallible;
use geo::EuclideanDistance; use geo::EuclideanDistance;
use petgraph::{data::DataMap, visit::EdgeRef}; use petgraph::{data::DataMap, visit::EdgeRef};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -16,7 +14,7 @@ use crate::{
Collision, DrawingException, Infringement, Collision, DrawingException, Infringement,
}, },
geometry::{ geometry::{
primitive::{AccessPrimitiveShape, PrimitiveShape}, primitive::PrimitiveShape,
shape::{AccessShape, MeasureLength}, shape::{AccessShape, MeasureLength},
}, },
graph::{GetPetgraphIndex, MakeRef}, graph::{GetPetgraphIndex, MakeRef},