Merge pull request #855 from bu5hm4nn/feature/review-relays-issue-834

UI Review Relays section
This commit is contained in:
Michael Dilger 2024-09-13 00:12:08 +00:00 committed by GitHub
commit 81c17fe110
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 283 additions and 196 deletions

View File

@ -286,10 +286,9 @@ fn dm_posting_area(
ui.horizontal(|ui| {
let response = widgets::options_menu_button(ui, &app.theme, &app.assets);
let menu = widgets::MoreMenu::bubble(ui.next_auto_id())
.with_max_size(vec2(190.0, 40.0))
.with_min_size(vec2(190.0, 40.0))
.place_above(!read_setting!(posting_area_at_top));
let menu =
widgets::MoreMenu::bubble(ui.next_auto_id(), vec2(190.0, 40.0), vec2(190.0, 40.0))
.place_above(!read_setting!(posting_area_at_top));
let mut items: Vec<MoreMenuItem> = Vec::new();
if app.dm_draft_data.include_subject {
@ -589,10 +588,12 @@ fn real_posting_area(app: &mut GossipUi, ctx: &Context, ui: &mut Ui) {
// show advanced action menu
if app.draft_data.repost.is_none() {
let response = widgets::options_menu_button(ui, &app.theme, &app.assets);
let menu = widgets::MoreMenu::bubble(ui.next_auto_id())
.with_max_size(vec2(180.0, 80.0))
.with_min_size(vec2(180.0, 80.0))
.place_above(!read_setting!(posting_area_at_top));
let menu = widgets::MoreMenu::bubble(
ui.next_auto_id(),
vec2(180.0, 80.0),
vec2(180.0, 80.0),
)
.place_above(!read_setting!(posting_area_at_top));
let mut items: Vec<MoreMenuItem> = Vec::new();

View File

@ -1139,21 +1139,6 @@ impl GossipUi {
self.add_menu_item_page(ui, Page::RelaysActivityMonitor, None, true);
self.add_menu_item_page(ui, Page::RelaysMine, None, true);
self.add_menu_item_page(ui, Page::RelaysKnownNetwork(None), None, true);
ui.vertical(|ui| {
ui.spacing_mut().button_padding *= 2.0;
ui.visuals_mut().widgets.inactive.weak_bg_fill =
self.theme.accent_color().linear_multiply(0.2);
ui.visuals_mut().widgets.inactive.fg_stroke.width = 1.0;
ui.visuals_mut().widgets.hovered.weak_bg_fill = self.theme.navigation_text_color();
ui.visuals_mut().widgets.hovered.fg_stroke.color = self.theme.accent_color();
if ui
.button(RichText::new("Add Relay"))
.on_hover_cursor(egui::CursorIcon::PointingHand)
.clicked()
{
relays::start_entry_dialog(self);
}
});
});
self.after_openable_menu(ui, &cstate);
}

View File

@ -302,13 +302,11 @@ pub(super) fn update(
let response = widgets::Button::primary(&app.theme, text)
.small(true)
.show(ui);
let menu =
widgets::MoreMenu::bubble(ui.auto_id_with(person.pubkey))
.with_min_size(vec2(100.0, 0.0))
.with_max_size(vec2(
100.0,
ctx.available_rect().height(),
));
let menu = widgets::MoreMenu::bubble(
ui.auto_id_with(person.pubkey),
vec2(100.0, 0.0),
vec2(100.0, ctx.available_rect().height()),
);
let mut items: Vec<MoreMenuItem> = Vec::new();
// actions
@ -780,9 +778,11 @@ pub(super) fn render_more_list_actions(
.small(true)
.show(ui);
let menu = widgets::MoreMenu::bubble(ui.next_auto_id())
.with_min_size(vec2(100.0, 0.0))
.with_max_size(vec2(140.0, ui.ctx().available_rect().height()));
let menu = widgets::MoreMenu::bubble(
ui.next_auto_id(),
vec2(100.0, 0.0),
vec2(140.0, ui.ctx().available_rect().height()),
);
let mut items: Vec<MoreMenuItem> = Vec::new();
items.push(MoreMenuItem::Button(MoreMenuButton::new(

View File

@ -5,12 +5,12 @@ use crate::ui::widgets;
use crate::ui::Page;
use eframe::egui;
use egui::{Context, Ui};
use egui_winit::egui::{Id, RichText};
use egui_winit::egui::Id;
use gossip_lib::Relay;
use gossip_lib::GLOBALS;
use nostr_types::RelayUrl;
pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
let is_editing = app.relays.edit.is_some();
widgets::page_header(ui, Page::RelaysActivityMonitor.name(), |ui| {
if is_editing {
@ -23,14 +23,13 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra
super::relay_sort_combo(app, ui);
btn_h_space!(ui);
widgets::TextEdit::search(&app.theme, &app.assets, &mut app.relays.search)
.desired_width(200.0)
.desired_width(150.0)
.show(ui);
if ui
.button(RichText::new(Page::RelaysCoverage.name()))
.on_hover_cursor(egui::CursorIcon::PointingHand)
if widgets::Button::primary(&app.theme, "Add Relay")
.show(ui)
.clicked()
{
app.set_page(ctx, crate::ui::Page::RelaysCoverage);
super::start_entry_dialog(app);
}
});

View File

@ -19,8 +19,14 @@ pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Fr
super::relay_sort_combo(app, ui);
btn_h_space!(ui);
widgets::TextEdit::search(&app.theme, &app.assets, &mut app.relays.search)
.desired_width(200.0)
.desired_width(150.0)
.show(ui);
if widgets::Button::primary(&app.theme, "Add Relay")
.show(ui)
.clicked()
{
super::start_entry_dialog(app);
}
});
// TBD time how long this takes. We don't want expensive code in the UI

View File

@ -21,14 +21,19 @@ pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Fr
super::relay_sort_combo(app, ui);
btn_h_space!(ui);
widgets::TextEdit::search(&app.theme, &app.assets, &mut app.relays.search)
.desired_width(200.0)
.desired_width(150.0)
.show(ui);
widgets::set_important_button_visuals(ui, app);
if widgets::Button::primary(&app.theme, "Add Relay")
.show(ui)
.clicked()
{
super::start_entry_dialog(app);
}
let advertise_remaining = GLOBALS.advertise_jobs_remaining.load(Ordering::Relaxed);
if advertise_remaining == 0 {
if ui.button("Advertise Relay List")
.on_hover_cursor(egui::CursorIcon::PointingHand)
if widgets::Button::secondary(&app.theme,"Advertise Relay List")
.show(ui)
.on_hover_text("Advertise my relays. Will send your relay usage information to every relay that seems to be working well so that other people know how to follow and contact you.")
.clicked()
{
@ -39,7 +44,10 @@ pub(super) fn update(app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Fr
} else {
ui.add_enabled(
false,
egui::Button::new(format!("Advertising, {} to go", advertise_remaining)),
widgets::Button::secondary(
&app.theme,
format!("Advertising, {} to go", advertise_remaining),
),
);
}
});

View File

@ -1,9 +1,12 @@
use std::cmp::Ordering;
use super::{widgets, GossipUi, Page};
use super::{
widgets::{self, MoreMenuButton, MoreMenuItem, MoreMenuSwitch},
GossipUi, Page,
};
use eframe::egui;
use egui::{Context, Ui};
use egui_winit::egui::{vec2, Id, Rect, RichText};
use egui_winit::egui::{vec2, Id, RichText};
use gossip_lib::{comms::ToOverlordMessage, Relay, GLOBALS};
use nostr_types::RelayUrl;
@ -295,58 +298,17 @@ pub(super) fn stop_entry_dialog(app: &mut GossipUi) {
pub(super) fn entry_dialog(ctx: &Context, app: &mut GossipUi) {
let dlg_size = vec2(ctx.screen_rect().width() * 0.66, 120.0);
egui::Area::new(Id::new("hide-background-area"))
.fixed_pos(ctx.screen_rect().left_top())
.movable(false)
.interactable(false)
.order(egui::Order::Middle)
.show(ctx, |ui| {
ui.painter().rect_filled(
ctx.screen_rect(),
egui::Rounding::same(0.0),
egui::Color32::from_rgba_unmultiplied(0, 0, 0, 80),
);
});
let id: Id = "relays-add-dialog".into();
let mut frame = egui::Frame::popup(&ctx.style());
let area = egui::Area::new(id)
.movable(false)
.interactable(true)
.order(egui::Order::Foreground)
.fixed_pos(ctx.screen_rect().center() - vec2(dlg_size.x / 2.0, dlg_size.y));
area.show(ctx, |ui| {
frame.fill = ui.visuals().extreme_bg_color;
frame.inner_margin = egui::Margin::symmetric(20.0, 10.0);
frame.show(ui, |ui| {
ui.set_min_size(dlg_size);
ui.set_max_size(dlg_size);
// ui.max_rect is inner_margin size
let tr = ui.max_rect().right_top();
ui.vertical(|ui| {
ui.horizontal(|ui| {
ui.heading("Add a new relay");
let rect = Rect::from_x_y_ranges(tr.x..=tr.x + 10.0, tr.y - 20.0..=tr.y - 10.0);
ui.allocate_ui_at_rect(rect, |ui| {
if ui
.add_sized(rect.size(), super::widgets::NavItem::new("\u{274C}", false))
.clicked()
{
stop_entry_dialog(app);
}
});
});
match app.relays.add_dialog_step {
AddRelayDialogStep::Inactive => {}
AddRelayDialogStep::Step1UrlEntry => entry_dialog_step1(ui, ctx, app),
AddRelayDialogStep::Step2AwaitOverlord => entry_dialog_step2(ui, app),
}
});
});
let response = widgets::modal_popup(ctx, dlg_size, dlg_size, true, |ui| {
match app.relays.add_dialog_step {
AddRelayDialogStep::Inactive => {}
AddRelayDialogStep::Step1UrlEntry => entry_dialog_step1(ui, ctx, app),
AddRelayDialogStep::Step2AwaitOverlord => entry_dialog_step2(ui, app),
}
});
if response.inner.clicked() || response.response.clicked_elsewhere() {
stop_entry_dialog(app);
}
}
fn entry_dialog_step1(ui: &mut Ui, ctx: &Context, app: &mut GossipUi) {
@ -467,20 +429,40 @@ fn entry_dialog_step2(ui: &mut Ui, app: &mut GossipUi) {
pub(super) fn configure_list_btn(app: &mut GossipUi, ui: &mut Ui) {
ui.add_enabled_ui(true, |ui| {
let min_size = vec2(180.0, 20.0);
let max_size = vec2(180.0, ui.ctx().available_rect().height());
let response = widgets::options_menu_button(ui, &app.theme, &app.assets);
widgets::MoreMenu::bubble(ui.next_auto_id())
.with_min_size(min_size)
.with_hover_text("Configure List View".to_owned())
.show(ui, response, |ui, _is_open| {
widgets::Switch::small(&app.theme, &mut app.relays.show_details)
.with_label("Show details")
.show(ui);
ui.add_space(8.0);
widgets::Switch::small(&app.theme, &mut app.relays.show_hidden)
.with_label("Show hidden relays")
.show(ui);
});
let text = egui::RichText::new("=").size(13.0);
let response = widgets::Button::primary(&app.theme, text)
.small(true)
.show(ui);
let menu = widgets::MoreMenu::bubble(ui.next_auto_id(), min_size, max_size);
let mut items: Vec<MoreMenuItem> = Vec::new();
items.push(MoreMenuItem::Switch(MoreMenuSwitch::new(
"Show details",
app.relays.show_details,
Box::new(|_ui, app| {
app.relays.show_details = !app.relays.show_details;
}),
)));
items.push(MoreMenuItem::Switch(MoreMenuSwitch::new(
"Show hidden relays",
app.relays.show_hidden,
Box::new(|_ui, app| {
app.relays.show_hidden = !app.relays.show_hidden;
}),
)));
items.push(MoreMenuItem::Button(MoreMenuButton::new(
"Relay Coverage",
Box::new(|ui, app| {
app.set_page(ui.ctx(), crate::ui::Page::RelaysCoverage);
}),
)));
menu.show_entries(ui, app, response, items);
});
}

View File

@ -18,32 +18,33 @@ impl DefaultTheme {
}
}
// Trait for creating different types of shadows
pub trait ShadowBuilder {
fn soft_dark() -> Self;
fn soft_light() -> Self;
}
/// Trait for creating different types of shadows
/// TODO @dtonon: This must be reviewed as shadow interface changed with egui 0.28
// pub trait ShadowBuilder {
// fn soft_dark() -> Self;
// fn soft_light() -> Self;
// }
// Implement the trait for Shadow
impl ShadowBuilder for Shadow {
fn soft_dark() -> Self {
Self {
offset: vec2(6.0, 10.0),
blur: 30.0,
spread: 0.0,
color: Color32::from_black_alpha(40),
}
}
// // Implement the trait for Shadow
// impl ShadowBuilder for Shadow {
// fn soft_dark() -> Self {
// Self {
// offset: vec2(6.0, 10.0),
// blur: 30.0,
// spread: 0.0,
// color: Color32::from_black_alpha(40),
// }
// }
fn soft_light() -> Self {
Self {
offset: vec2(6.0, 10.0),
blur: 30.0,
spread: 0.0,
color: Color32::from_black_alpha(10),
}
}
}
// fn soft_light() -> Self {
// Self {
// offset: vec2(6.0, 10.0),
// blur: 30.0,
// spread: 0.0,
// color: Color32::from_black_alpha(10),
// }
// }
// }
impl ThemeDef for DefaultTheme {
fn name() -> &'static str {

View File

@ -355,7 +355,7 @@ fn button_test(app: &mut GossipUi, ui: &mut Ui) {
fn textedit_test(app: &mut GossipUi, ui: &mut Ui) {
ui.horizontal(|ui| {
ui.heading("Button Test:");
ui.heading("TextEdit Test:");
ui.add_space(30.0);
});
ui.add_space(30.0);
@ -428,6 +428,32 @@ fn textedit_test(app: &mut GossipUi, ui: &mut Ui) {
.show(ui);
});
});
ui.add_space(20.0);
ui.horizontal(|ui| {
ui.add_sized(CSIZE, egui::Label::new("with Paste"));
ui.add_space(20.0);
ui.vertical(|ui| {
let output =
widgets::TextEdit::singleline(theme, &mut app.theme_test.textedit_empty)
.hint_text(HINT)
.with_paste()
.show(ui);
if ui.link("focus").clicked() {
output.response.request_focus();
}
});
ui.add_space(20.0);
ui.vertical(|ui| {
let output =
widgets::TextEdit::search(theme, assets, &mut app.theme_test.textedit_empty)
.hint_text(HINT)
.with_paste()
.show(ui);
if ui.link("focus").clicked() {
output.response.request_focus();
}
});
});
});
}

View File

@ -34,7 +34,7 @@ const HLINE_THICKNESS: f32 = 1.5;
pub(crate) fn allocate_space(ui: &mut Ui, height: f32) -> (Rect, Response) {
let available_width = ui.available_size_before_wrap().x;
ui.allocate_exact_size(vec2(available_width, height), Sense::hover())
ui.allocate_exact_size(vec2(available_width, height), Sense::click())
}
pub(crate) fn paint_frame(ui: &mut Ui, rect: &Rect, fill: Option<Color32>) {

View File

@ -29,7 +29,9 @@ mod modal_popup;
pub use modal_popup::{modal_popup, modal_popup_dyn, ModalEntry};
mod more_menu;
pub(super) use more_menu::{MoreMenu, MoreMenuButton, MoreMenuItem, MoreMenuSubMenu};
pub(super) use more_menu::{
MoreMenu, MoreMenuButton, MoreMenuItem, MoreMenuSubMenu, MoreMenuSwitch,
};
mod information_popup;
pub use information_popup::InformationPopup;

View File

@ -27,6 +27,7 @@ enum MoreMenuStyle {
pub(in crate::ui) enum MoreMenuItem<'a> {
Button(MoreMenuButton<'a>),
SubMenu(MoreMenuSubMenu<'a>),
Switch(MoreMenuSwitch<'a>),
}
#[allow(clippy::type_complexity)]
@ -65,7 +66,7 @@ impl<'a> MoreMenuButton<'a> {
galley.rect.width()
}
fn show(self, app: &mut GossipUi, ui: &mut Ui) -> Response {
pub fn show(self, app: &mut GossipUi, ui: &mut Ui) -> Response {
if !self.enabled {
ui.disable();
}
@ -133,7 +134,7 @@ impl<'a> MoreMenuSubMenu<'a> {
}
}
fn show(self, app: &mut GossipUi, ui: &mut Ui) -> Response {
pub fn show(self, app: &mut GossipUi, ui: &mut Ui) -> Response {
if !self.enabled {
ui.disable();
}
@ -155,6 +156,7 @@ impl<'a> MoreMenuSubMenu<'a> {
.map(|item| match item {
MoreMenuItem::Button(entry) => entry.calc_min_width(ui),
MoreMenuItem::SubMenu(menu) => menu.calc_min_width(ui),
MoreMenuItem::Switch(switch) => switch.calc_min_width(ui),
})
.reduce(f32::max)
.unwrap_or(150.0)
@ -221,6 +223,9 @@ impl<'a> MoreMenuSubMenu<'a> {
open = false;
}
}
MoreMenuItem::Switch(switch) => {
switch.show(app, ui);
}
});
}
})
@ -252,6 +257,65 @@ impl<'a> MoreMenuSubMenu<'a> {
}
}
pub(in crate::ui) struct MoreMenuSwitch<'a> {
text: WidgetText,
value: bool,
action: Box<dyn FnOnce(&mut Ui, &mut GossipUi) + 'a>,
enabled: bool,
}
impl<'a> MoreMenuSwitch<'a> {
#[allow(clippy::type_complexity)]
pub fn new(
text: impl Into<WidgetText>,
value: bool,
action: Box<dyn FnOnce(&mut Ui, &mut GossipUi) + 'a>,
) -> Self {
Self {
text: text.into(),
value,
action,
enabled: true,
}
}
#[allow(unused)]
pub fn enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}
fn calc_min_width(&self, ui: &Ui) -> f32 {
let galley = ui.fonts(|f| {
f.layout_no_wrap(
self.text.text().into(),
egui::TextStyle::Body.resolve(ui.style()),
egui::Color32::BLACK,
)
});
galley.rect.width() + super::Switch::small_size().x
}
pub fn show(self, app: &mut GossipUi, ui: &mut Ui) -> Response {
if !self.enabled {
ui.disable();
}
let mut value = self.value;
let response = super::Switch::small(&app.theme, &mut value)
.with_label(self.text)
.with_padding(vec2(10.0, 5.0))
.show(ui);
// process action
if response.clicked() {
(self.action)(ui, app);
}
response
}
}
pub(in crate::ui) struct MoreMenu {
id: Id,
min_size: Vec2,
@ -276,14 +340,11 @@ impl MoreMenu {
}
}
pub fn bubble(id: Id) -> Self {
pub fn bubble(id: Id, min_size: Vec2, max_size: Vec2) -> Self {
Self {
id,
min_size: Vec2 { x: 0.0, y: 0.0 },
max_size: Vec2 {
x: f32::INFINITY,
y: f32::INFINITY,
},
min_size,
max_size,
above_or_below: None,
hover_text: None,
style: MoreMenuStyle::Bubble,
@ -517,6 +578,9 @@ impl MoreMenu {
active = false;
}
}
MoreMenuItem::Switch(switch) => {
switch.show(app, ui);
}
});
}
})

View File

@ -192,8 +192,7 @@ pub struct RelayEntry {
accent: Color32,
accent_hover: Color32,
bg_fill: Color32,
// highlight: Option<Color32>,
option_symbol: TextureId,
bg_hover: Color32,
auth_require_permission: bool,
conn_require_permission: bool,
}
@ -205,6 +204,16 @@ impl RelayEntry {
let mut hsva: ecolor::HsvaGamma = accent.into();
hsva.v *= 0.8;
let accent_hover: Color32 = hsva.into();
let bg_fill = if app.theme.dark_mode {
app.theme.neutral_800()
} else {
app.theme.neutral_100()
};
let bg_hover = if app.theme.dark_mode {
app.theme.neutral_950()
} else {
app.theme.neutral_50()
};
Self {
relay,
view: RelayEntryView::List,
@ -216,9 +225,8 @@ impl RelayEntry {
usage,
accent,
accent_hover,
bg_fill: app.theme.main_content_bgcolor(),
// highlight: None,
option_symbol: (&app.assets.options_symbol).into(),
bg_fill,
bg_hover,
auth_require_permission: false,
conn_require_permission: false,
}
@ -332,29 +340,6 @@ impl RelayEntry {
.on_hover_text(tooltip);
}
fn paint_edit_btn(&mut self, ui: &mut Ui, rect: &Rect) -> Response {
let id = self.make_id("edit_btn");
let pos = rect.right_top() + vec2(-EDIT_BTN_SIZE - TEXT_RIGHT, TEXT_TOP);
let btn_rect = Rect::from_min_size(pos, vec2(EDIT_BTN_SIZE, EDIT_BTN_SIZE));
let response = ui
.interact(btn_rect, id, Sense::click())
.on_hover_cursor(CursorIcon::PointingHand)
.on_hover_text("Configure Relay");
let color = if response.hovered() {
ui.visuals().text_color()
} else {
self.accent
};
let mut mesh = Mesh::with_texture(self.option_symbol);
mesh.add_rect_with_uv(
btn_rect.shrink(2.0),
Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)),
color,
);
ui.painter().add(Shape::mesh(mesh));
response
}
fn paint_close_btn(&mut self, ui: &mut Ui, rect: &Rect) -> Response {
let id = self.make_id("close_btn");
let button_padding = ui.spacing().button_padding;
@ -580,8 +565,7 @@ impl RelayEntry {
const SPACE: f32 = 23.0;
// match self.view { RelayEntryView::Detail => ... }
let right = pos2(rect.max.x, rect.min.y)
+ vec2(-TEXT_RIGHT - EDIT_BTN_SIZE - SPACE, TEXT_TOP + 4.0);
let right = pos2(rect.max.x, rect.min.y) + vec2(-TEXT_RIGHT, TEXT_TOP + 4.0);
let align = Align::Center;
@ -1222,15 +1206,23 @@ impl RelayEntry {
(self.relay.url.to_string() + str).into()
}
fn interact_bg_color(&self, response: &Response) -> Option<Color32> {
if response.hovered() {
Some(self.bg_hover)
} else {
Some(self.bg_fill)
}
}
/// Do layout and position the galley in the ui, without painting it or adding widget info.
fn update_list_view(mut self, ui: &mut Ui) -> Response {
fn update_list_view(self, ui: &mut Ui) -> Response {
let (rect, mut response) = list_entry::allocate_space(ui, LIST_VIEW_HEIGHT);
response = response.on_hover_cursor(egui::CursorIcon::PointingHand);
// all the heavy lifting is only done if it's actually visible
if ui.is_rect_visible(rect) {
list_entry::paint_frame(ui, &rect, Some(self.bg_fill));
list_entry::paint_frame(ui, &rect, self.interact_bg_color(&response));
self.paint_title(ui, &rect);
response |= self.paint_edit_btn(ui, &rect);
if self.relay.has_any_usage_bit() || self.relay.is_good_for_advertise() {
self.paint_usage(ui, &rect);
} else {
@ -1242,14 +1234,14 @@ impl RelayEntry {
response
}
fn update_detail_view(mut self, ui: &mut Ui) -> Response {
fn update_detail_view(self, ui: &mut Ui) -> Response {
let (rect, mut response) = list_entry::allocate_space(ui, DETAIL_VIEW_HEIGHT);
response = response.on_hover_cursor(egui::CursorIcon::PointingHand);
// all the heavy lifting is only done if it's actually visible
if ui.is_rect_visible(rect) {
list_entry::paint_frame(ui, &rect, Some(self.bg_fill));
list_entry::paint_frame(ui, &rect, self.interact_bg_color(&response));
self.paint_title(ui, &rect);
response |= self.paint_edit_btn(ui, &rect);
self.paint_stats(ui, &rect);
if self.relay.has_any_usage_bit() || self.relay.is_good_for_advertise() {
self.paint_usage(ui, &rect);

View File

@ -14,9 +14,20 @@ pub struct Switch<'a> {
label: Option<WidgetText>,
label_color: Option<Color32>,
size: Vec2,
padding: Vec2,
theme: &'a Theme,
}
impl Switch<'_> {
pub const fn small_size() -> Vec2 {
vec2(29.0, 16.0)
}
pub const fn large_size() -> Vec2 {
vec2(40.0, 22.0)
}
}
impl<'a> Switch<'a> {
/// Create a small switch, similar to normal line height
pub fn small(theme: &'a Theme, value: &'a mut bool) -> Self {
@ -24,7 +35,8 @@ impl<'a> Switch<'a> {
value,
label: None,
label_color: None,
size: vec2(29.0, 16.0),
size: Switch::small_size(),
padding: Vec2::ZERO,
theme,
}
}
@ -35,7 +47,8 @@ impl<'a> Switch<'a> {
value,
label: None,
label_color: None,
size: vec2(40.0, 22.0),
size: Switch::large_size(),
padding: Vec2::ZERO,
theme,
}
}
@ -51,6 +64,11 @@ impl<'a> Switch<'a> {
self
}
pub fn with_padding(mut self, padding: Vec2) -> Self {
self.padding = padding;
self
}
pub fn show(mut self, ui: &mut Ui) -> Response {
let (response, galley) = self.allocate(ui);
let (state, response) = interact(ui, response, self.value, self.label);
@ -60,6 +78,7 @@ impl<'a> Switch<'a> {
self.value,
response,
self.size,
self.padding,
galley,
self.label_color,
state,
@ -94,7 +113,9 @@ impl<'a> Switch<'a> {
egui::Sense::hover()
};
// allocate
let (_, response) = ui.allocate_exact_size(self.size + vec2(extra_width, 0.0), sense);
let size = self.size + vec2(extra_width, 0.0);
let size = size + self.padding + self.padding;
let (_, response) = ui.allocate_exact_size(size, sense);
(response, galley)
}
@ -229,6 +250,7 @@ fn draw_at(
value: &bool,
response: Response,
size: Vec2,
padding: Vec2,
galley: Option<Arc<Galley>>,
label_color: Option<Color32>,
_state: WidgetState,
@ -237,7 +259,7 @@ fn draw_at(
if ui.is_rect_visible(rect) {
let how_on = ui.ctx().animate_bool(response.id, *value);
let radius = 0.5 * rect.height();
let radius = 0.5 * size.y;
let stroke_width = 0.5;
let (bg_fill, frame_stroke, knob_fill, knob_stroke, text_color) = if theme.dark_mode {
if ui.is_enabled() {
@ -304,7 +326,7 @@ fn draw_at(
};
// switch
let switch_rect = Rect::from_min_size(rect.min, size);
let switch_rect = Rect::from_min_size(rect.min + padding, size);
ui.painter()
.rect(switch_rect, radius, bg_fill, frame_stroke);
let circle_x = egui::lerp(

View File

@ -157,12 +157,12 @@ impl<'t> TextEdit<'t> {
// ---- show inner ----
let output = inner.show(ui);
let response = &output.response;
let frame_rect = response.rect + margin;
// ---- draw frame ----
{
let theme = self.theme;
let response = &output.response;
let frame_rect = response.rect + margin;
// this is how egui chooses the visual style:
#[allow(clippy::if_same_then_else)]
@ -200,8 +200,7 @@ impl<'t> TextEdit<'t> {
if self.with_search {
if let Some(symbol) = self.magnifyingglass_symbol {
let rect = Rect::from_center_size(
output.response.rect.left_center()
+ vec2((MARGIN.left + pre_space) / 2.0, 0.0),
frame_rect.left_center() + vec2((MARGIN.left + pre_space) / 2.0, 0.0),
symbol.size_vec2() / (assets::SVG_OVERSAMPLE + ui.ctx().zoom_factor()),
);
egui::Image::from_texture(SizedTexture::new(symbol.id(), symbol.size_vec2()))
@ -217,8 +216,8 @@ impl<'t> TextEdit<'t> {
if self.with_clear && !self.text.as_str().is_empty() {
let rect = Rect::from_min_size(
output.response.rect.right_top() - vec2(output.response.rect.height(), 0.0),
vec2(output.response.rect.height(), output.response.rect.height()),
frame_rect.right_top() - vec2(frame_rect.height(), 0.0),
vec2(frame_rect.height(), frame_rect.height()),
);
// clear button
@ -266,9 +265,9 @@ impl<'t> TextEdit<'t> {
}
};
let action_size = vec2(45.0, output.response.rect.height());
let action_size = vec2(45.0, frame_rect.height());
let rect = Rect::from_min_size(
output.response.rect.right_top() - vec2(action_size.x, 0.0),
frame_rect.right_top() - vec2(action_size.x, 0.0),
action_size,
);