Updated to egui 0.15

pull/4/head
Benedikt Terhechte 3 years ago
parent 682eb20754
commit 58940b1b51

102
Cargo.lock generated

@ -575,11 +575,12 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "eframe"
version = "0.14.0"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aeeebd536f1a2737661be42819ed58a7aac69a4bf061610b373467f886574e6"
checksum = "3a084390b90aa223d5fb6ee3d2ac3a2ded0df212f684f91fbb5f0f45ab9e0724"
dependencies = [
"egui",
"egui-winit",
"egui_glium",
"egui_web",
"epi",
@ -587,31 +588,45 @@ dependencies = [
[[package]]
name = "egui"
version = "0.14.2"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b403f29d592b5c2267279bfdf2cd3fe3ba0e7a8738d03203a6f1536e8e9d26bd"
checksum = "1c8d416a3343cbfc6f4d17bb1cba46b4d7efecb9ee541967763e0b5e04e5fae7"
dependencies = [
"ahash",
"epaint",
"nohash-hasher",
]
[[package]]
name = "egui_glium"
version = "0.14.0"
name = "egui-winit"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "972b1882ae98f7dd2f5dcbf5efeb35448c158a8f6ba80d6cc3b8073eae1fae4f"
checksum = "bc403e91d1bd693239f1c734193cdf0eb38c8682bbfb9990c4b6cd2db5ee368e"
dependencies = [
"copypasta",
"egui",
"epi",
"glium",
"webbrowser",
"winit",
]
[[package]]
name = "egui_glium"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26478ec89b8c9c41a45687a90f9c8fc18106e3ffd8a08559285d625185a2ac92"
dependencies = [
"egui",
"egui-winit",
"epi",
"glium",
]
[[package]]
name = "egui_web"
version = "0.14.1"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a70a7eee03a31589660cbfefa5ac529b9740b008d94075c46fd29f80abfad9de"
checksum = "43f2af8984a1c9ecaaaf7f11424c78185c89b5cfe8dab3bd0fac641db81c5763"
dependencies = [
"egui",
"epi",
@ -638,9 +653,9 @@ dependencies = [
[[package]]
name = "emath"
version = "0.14.0"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cca5179aa9d15128cebb79bb56dda73a79cc66b402056ff19a992e54b365e15c"
checksum = "24a1aaa922d55da6a2bf32957c3d153e7fb9d52ed8d69777a75092240172eb6e"
[[package]]
name = "emlx"
@ -654,22 +669,22 @@ dependencies = [
[[package]]
name = "epaint"
version = "0.14.0"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "136e7d88da926182bcfdb8217137dd347dfe5dc03b8988eaba3ef8becf83394a"
checksum = "16bb4d3b8bbbd132c99d2a5efec8567e8b6d09b742f758ae6cf1e4b104fe0231"
dependencies = [
"ab_glyph",
"ahash",
"atomic_refcell",
"emath",
"ordered-float",
"nohash-hasher",
]
[[package]]
name = "epi"
version = "0.14.0"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c033c9b4d921566a98b8831b63af5ba2a0ad7ffa62d22b897698f36c22a28a"
checksum = "3f5e4e08127f9b86e2c450c96a3032764b63546eb170c2fc54684dc70ff3fc82"
dependencies = [
"egui",
]
@ -1085,9 +1100,9 @@ dependencies = [
[[package]]
name = "libsqlite3-sys"
version = "0.22.2"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d"
checksum = "abd5850c449b40bacb498b2bbdfaff648b1b055630073ba8db499caf2d0ea9f2"
dependencies = [
"pkg-config",
"vcpkg",
@ -1324,6 +1339,12 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
[[package]]
name = "nohash-hasher"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
[[package]]
name = "nom"
version = "7.0.0"
@ -1471,15 +1492,6 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "ordered-float"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97c9d06878b3a851e8026ef94bf7fef9ba93062cd412601da4d9cf369b1cc62d"
dependencies = [
"num-traits",
]
[[package]]
name = "osmesa-sys"
version = "0.1.2"
@ -1659,8 +1671,8 @@ dependencies = [
"serde",
"serde_json",
"shellexpand",
"strum",
"strum_macros",
"strum 0.22.0",
"strum_macros 0.22.0",
"thiserror",
"tracing",
"tracing-subscriber",
@ -1862,9 +1874,9 @@ dependencies = [
[[package]]
name = "rusqlite"
version = "0.25.3"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57adcf67c8faaf96f3248c2a7b419a0dbc52ebe36ba83dd57fe83827c1ea4eb3"
checksum = "8a82b0b91fad72160c56bf8da7a549b25d7c31109f52cc1437eac4c0ad2550a7"
dependencies = [
"bitflags",
"chrono",
@ -1948,9 +1960,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.68"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
checksum = "e277c495ac6cd1a01a58d0a0c574568b4d1ddf14f59965c6a58b8d96400b54f3"
dependencies = [
"itoa",
"ryu",
@ -2055,6 +2067,12 @@ version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2"
[[package]]
name = "strum"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e"
[[package]]
name = "strum_macros"
version = "0.21.1"
@ -2067,6 +2085,18 @@ dependencies = [
"syn",
]
[[package]]
name = "strum_macros"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "1.0.77"
@ -2089,8 +2119,8 @@ dependencies = [
"heck",
"itertools",
"pkg-config",
"strum",
"strum_macros",
"strum 0.21.0",
"strum_macros 0.21.1",
"thiserror",
"toml",
"version-compare",

@ -25,29 +25,29 @@ eyre = "0.6.5"
thiserror = "1.0.29"
tracing = "0.1.29"
tracing-subscriber = "0.3.0"
rusqlite = {version = "0.25.3", features = ["chrono", "trace", "serde_json"]}
rusqlite = {version = "0.26.1", features = ["chrono", "trace", "serde_json"]}
regex = "1.5.3"
flate2 = "1.0.22"
once_cell = "1.8.0"
email-parser = { git = "https://github.com/terhechte/email-parser", features = ["sender", "to", "in-reply-to", "date", "subject", "mime", "allow-duplicate-headers", "compatibility-fixes"]}
rayon = "1.5.1"
chrono = "0.4.19"
serde_json = "*"
serde = { version = "*", features = ["derive"]}
serde_json = "1.0.70"
serde = { version = "1.0.130", features = ["derive"]}
crossbeam-channel = "0.5.1"
eframe = { version = "*", optional = true}
eframe = { version = "0.15.0", optional = true}
rsql_builder = "0.1.2"
treemap = "0.3.2"
num-format = "0.4.0"
strum = "0.21"
strum_macros = "0.21"
strum = "0.22.0"
strum_macros = "0.22.0"
lru = { version = "0.7.0", optional = true }
emlx = { git = "https://github.com/terhechte/emlx", features = []}
walkdir = "*"
walkdir = "2.3.2"
mbox-reader = "0.2.0"
rfd = "0.5.1"
rand = "0.8.4"
shellexpand = "*"
shellexpand = "2.1.0"
image = { version = "0.23", default-features = false, features = ["png"] }
[features]

@ -75,7 +75,7 @@ impl ErrorUI {
}
ui.add_space(30.0);
if self.show_details {
egui::containers::ScrollArea::auto_sized().show(ui, |ui| {
egui::containers::ScrollArea::vertical().show(ui, |ui| {
ui.add(
egui::widgets::Label::new("Error Chain")
.text_style(egui::TextStyle::Heading),

@ -214,21 +214,22 @@ impl StartupUI {
let button_size1: Vec2 = ((center.width() / 2.0) - 25.0, 25.0).into();
let button_size2: Vec2 = ((center.width() / 2.0) - 25.0, 25.0).into();
ui.horizontal(|ui| {
let response = ui.add_sized(
button_size1,
egui::Button::new("Start")
.enabled(
let enabled = {
// if we have an email folder,
// and - if we want to save to disk -
// if we have a database path
self.email_folder.is_some() &&
(self.save_to_disk == self.database_path.is_some())
)
.text_color(colors.text_primary),
);
if response.clicked() {
self.action_start();
}
};
ui.add_enabled_ui(enabled, |ui| {
let response = ui.add_sized(
button_size1,
egui::Button::new("Start").text_color(colors.text_primary),
);
if response.clicked() {
self.action_start();
}
});
let response = ui.add_sized(button_size2, egui::Button::new("Or Open Database"));
if response.clicked() {
self.action_open_database();

@ -1,5 +1,5 @@
use crate::model::Engine;
use eframe::egui::{self, Widget};
use eframe::egui::{self, Color32, Widget};
use eyre::Report;
use super::app_state::UIState;
@ -64,17 +64,21 @@ impl<'a> Widget for NavigationBar<'a> {
let mut w = ui.available_width();
let mail_text = "\u{1F4E7} Mails";
let mail_galley = ui
.painter()
.layout_no_wrap(egui::TextStyle::Button, mail_text.to_owned());
let mail_galley = ui.painter().layout_no_wrap(
mail_text.to_owned(),
egui::TextStyle::Button,
Color32::WHITE,
);
let filter_text = "\u{1F5B9} Export";
let filter_galley = ui
.painter()
.layout_no_wrap(egui::TextStyle::Button, filter_text.to_owned());
w -= mail_galley.size.x + ui.spacing().button_padding.x * 4.0;
w -= filter_galley.size.x + ui.spacing().button_padding.x * 4.0;
let filter_galley = ui.painter().layout_no_wrap(
filter_text.to_owned(),
egui::TextStyle::Button,
Color32::WHITE,
);
w -= mail_galley.size().x + ui.spacing().button_padding.x * 4.0;
w -= filter_galley.size().x + ui.spacing().button_padding.x * 4.0;
ui.add_space(w);
ui.add(navigation_button(filter_text));

@ -25,10 +25,11 @@ impl<'a> Widget for SegmentationBar<'a> {
for (id_index, group) in groupings.iter().enumerate() {
let alternatives = segmentations::aggregation_fields(self.engine, group);
if let Some(value) = group.value() {
let button = egui::Button::new(format!("{} {}", group.name(), value))
.enabled(false)
.text_color(egui::Color32::WHITE);
ui.add(button);
ui.add_enabled(
false,
egui::Button::new(format!("{} {}", group.name(), value))
.text_color(egui::Color32::WHITE),
);
} else if let Some(mut selected) = group.index(&alternatives) {
let p = egui::ComboBox::from_id_source(&id_index).show_index(
ui,

@ -1,6 +1,8 @@
//! Various background utilities
use eframe::egui::{
self, epaint::Shadow, vec2, Color32, Painter, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2,
self,
epaint::{RectShape, Shadow},
vec2, Color32, Painter, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2,
};
use std::ops::Rem;
@ -29,12 +31,12 @@ pub fn color_background(
ui.painter().set(
where_to_put_background,
egui::epaint::Shape::Rect {
egui::epaint::Shape::Rect(RectShape {
corner_radius: 0.0,
fill,
stroke,
rect,
},
}),
);
ret
}
@ -48,12 +50,12 @@ pub fn shadow_background(
corner_radius: f32,
shadow: Shadow,
) {
let frame_shape = Shape::Rect {
let frame_shape = Shape::Rect(RectShape {
rect: paint_rect,
corner_radius,
fill,
stroke,
};
});
let shadow = shadow.tessellate(paint_rect, corner_radius);
let shadow = Shape::Mesh(shadow);

@ -14,7 +14,7 @@ pub struct FilterState {
is_reply: Option<bool>,
is_seen: Option<bool>,
subject_contains: Option<String>,
tags_contains: Option<String>,
tags_contains: Option<Vec<String>>,
}
impl FilterState {
@ -41,6 +41,21 @@ impl<'a> Widget for FilterPanel<'a> {
let Self { engine, state } = self;
egui::Frame::none()
.margin(vec2(15.0, 10.5))
.show(ui, |ui| {
FilterPanel::filter_panel_contents(ui, engine, state)
})
.response
}
}
impl FilterPanel<'_> {
fn filter_panel_contents(
ui: &mut egui::Ui,
engine: &mut Engine,
state: &mut FilterState,
) -> Response {
egui::ScrollArea::vertical()
.max_height(330.0)
.show(ui, |ui| {
egui::Grid::new("filter_grid")
.spacing(vec2(15.0, 15.0))
@ -67,7 +82,12 @@ impl<'a> Widget for FilterPanel<'a> {
ui.end_row();
if engine.format_has_tags() {
input_block(ui, "Tags", &mut state.tags_contains);
input_tags(
ui,
"Tags",
&mut state.tags_contains,
engine.known_tags(),
);
ui.end_row();
}
});
@ -135,3 +155,19 @@ fn input_block(ui: &mut egui::Ui, title: &str, value: &mut Option<String>) {
_ => *value = Some(text_value),
}
}
fn input_tags(
ui: &mut egui::Ui,
title: &str,
selected: &mut Option<Vec<String>>,
available: &[String],
) {
let mut selected: String = "".to_owned();
ui.horizontal_wrapped(|ui| {
for tag in available {
//ui.label(tag);
ui.selectable_value(&mut selected, tag.clone(), tag);
}
});
ui.button("Clear");
}

@ -1,7 +1,10 @@
use std::collections::hash_map::DefaultHasher;
use crate::model::{segmentations, Engine, Segment};
use eframe::egui::{self, epaint::Galley, Color32, Pos2, Rect, Rgba, Stroke, TextStyle, Widget};
use eframe::{
egui::{self, epaint::Galley, Color32, Pos2, Rect, Rgba, Stroke, TextStyle, Widget},
epi::Frame,
};
use eyre::Report;
use num_format::{Locale, ToFormattedString};
@ -53,26 +56,30 @@ impl<'a> Widget for Rectangles<'a> {
response.mark_changed();
}
if item_response.hovered() {
hovered = Some(format!("#{}: {}", item.count, item.field.to_string()));
hovered = Some(format!("{}: #{}", item.field.to_string(), item.count));
}
}
if let Some(h) = hovered {
// Calculate the size
let text = format!("{}", h);
let galley = ui.painter().layout_no_wrap(TextStyle::Body, text.clone());
let galley = ui
.painter()
.layout_no_wrap(text.clone(), TextStyle::Body, Color32::WHITE);
// keep spacing in mind
let size = galley.size();
let size: Pos2 = (
galley.size.x + ui.spacing().button_padding.x * 2.0,
galley.size.y + ui.spacing().button_padding.y * 2.0,
size.x + ui.spacing().button_padding.x * 2.0,
size.y + ui.spacing().button_padding.y * 2.0,
)
.into();
// we build a disabled for easy rounded corners
let label_button = egui::widgets::Button::new(text)
.enabled(false)
.text_color(Color32::WHITE);
let label = egui::widgets::Label::new(text)
.background_color(colors.window_background)
.text_color(colors.text_primary);
// we want to be a wee bit in the rectangle system
let offset = -2.0;
@ -85,7 +92,7 @@ impl<'a> Widget for Rectangles<'a> {
.into(),
(size.x + 10.0, size.y + 10.0).into(),
),
label_button,
label,
);
}
@ -127,10 +134,11 @@ fn rectangle_ui(
let align_bottom = |galley: &std::sync::Arc<Galley>, center: &mut Pos2, spacing: f32| {
#[allow(clippy::clone_on_copy)]
let mut position = center.clone();
position.x -= galley.size.x / 2.0;
position.y -= galley.size.y / 2.0;
center.y += galley.size.y + spacing;
if galley.size.x < rect.width() && galley.size.y < rect.height() {
let size = galley.size();
position.x -= size.x / 2.0;
position.y -= size.y / 2.0;
center.y += size.y + spacing;
if size.x < rect.width() && size.y < rect.height() {
Some(position)
} else {
None
@ -142,10 +150,10 @@ fn rectangle_ui(
// Take the max width - some spacing to fit into the rectangle
let width = rect.width() - ui.spacing().button_padding.x * 2.0;
let text = segment.field.to_string();
let galley = painter.layout_multiline(TextStyle::Body, text, width);
let galley = painter.layout(text, TextStyle::Body, Rgba::BLACK.into(), width);
let previous_center = center;
if let Some(center) = align_bottom(&galley, &mut center, 2.0) {
painter.galley(center, galley, Rgba::BLACK.into());
painter.galley(center, galley);
} else {
// If the name doesn't fit, reverse the changes to center the count
center = previous_center;
@ -153,9 +161,9 @@ fn rectangle_ui(
}
{
let text = segment.count.to_formatted_string(&Locale::en);
let galley = painter.layout_no_wrap(TextStyle::Small, text);
let galley = painter.layout_no_wrap(text, TextStyle::Small, Rgba::BLACK.into());
if let Some(center) = align_bottom(&galley, &mut center, 5.0) {
painter.galley(center, galley, Rgba::BLACK.into());
painter.galley(center, galley);
}
}
response

@ -1,4 +1,6 @@
use eframe::egui::{self, lerp, vec2, Color32, Pos2, Response, Shape, Stroke, Vec2, Widget};
use eframe::egui::{
self, epaint::PathShape, lerp, vec2, Color32, Pos2, Response, Shape, Stroke, Vec2, Widget,
};
/// A simple spinner
pub struct Spinner(Vec2);
@ -31,12 +33,13 @@ impl Widget for Spinner {
+ vec2(-corner_radius, 0.0)
})
.collect();
ui.painter().add(Shape::Path {
let shape = Shape::Path(PathShape {
points,
closed: false,
fill: Color32::TRANSPARENT,
stroke: Stroke::new(8.0, visuals.strong_text_color()),
});
ui.painter().add(shape);
ui.ctx().request_repaint();

@ -129,9 +129,6 @@ impl<
let column_id = self.id_source.with("_column_").with(i);
let desired_column_width = state.column_width(i);
let galley = ui
.fonts()
.layout_single_line(header_text_style, column.name.clone());
let mut column_rect = rect;
column_rect.min.x += column_offset;
@ -143,6 +140,16 @@ impl<
let response = ui.interact(column_rect, column_id, Sense::hover());
let color = if response.hovered() {
ui.style().visuals.widgets.hovered.fg_stroke.color
} else {
ui.style().visuals.widgets.inactive.fg_stroke.color
};
let galley = ui
.fonts()
.layout_no_wrap(column.name.clone(), header_text_style, color);
if response.hovered() {
ui.painter().rect_stroke(
column_rect,
@ -153,16 +160,8 @@ impl<
let mut text_pos = column_rect.left_center();
text_pos.x += self.cell_padding.x;
text_pos.y -= galley.size.y / 2.0;
ui.painter_at(column_rect).galley(
text_pos,
galley,
if response.hovered() {
ui.style().visuals.widgets.hovered.fg_stroke.color
} else {
ui.style().visuals.widgets.inactive.fg_stroke.color
},
);
text_pos.y -= galley.size().y / 2.0;
ui.painter_at(column_rect).galley(text_pos, galley);
column_offset += column_rect.width();
}
@ -198,14 +197,14 @@ impl<
// First step: compute some sizes used during rendering. Since this is a
// homogenous table, we can figure out its exact sizes based on the
// number of rows and columns.
let table_rect = ui.available_rect_before_wrap_finite();
let table_rect = ui.available_rect_before_wrap();
let response = ui.interact(table_rect, self.id_source, Sense::hover());
self.header_ui(ui, &mut state);
// Now render the table body, which is inside an independently
// scrollable area.
ScrollArea::auto_sized().show_rows(ui, self.row_height, self.num_rows, |ui, row_range| {
ScrollArea::vertical().show_rows(ui, self.row_height, self.num_rows, |ui, row_range| {
ui.scope(|ui| {
let maker = &mut self.row_maker;
let rows = maker(row_range);
@ -272,12 +271,14 @@ impl<
let painter = ui.painter_at(column_rect);
let galley = ui.fonts().layout_single_line(cell_text_style, cell_text);
let galley =
ui.fonts()
.layout_no_wrap(cell_text, cell_text_style, cell_text_color);
let mut text_pos = column_rect.left_center();
text_pos.x += self.cell_padding.x;
text_pos.y -= galley.size.y / 2.0;
painter.galley(text_pos, galley, cell_text_color);
text_pos.y -= galley.size().y / 2.0;
painter.galley(text_pos, galley);
column_offset += column_rect.width();
}

Loading…
Cancel
Save