mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-29 08:21:47 +00:00
Merge pull request #817 from bu5hm4nn/feature/egui-upgrade
egui upgrade to 0.28.2
This commit is contained in:
commit
2d9b7b5fbd
485
Cargo.lock
generated
485
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@ resolver = "2"
|
||||
|
||||
[patch.crates-io]
|
||||
# override egui crate for egui_video dependency
|
||||
egui = { git = "https://github.com/bu5hm4nn/egui", rev = "63dde4c9b311da0cae0cb9f9465bf7273227be6c" }
|
||||
egui = { git = "https://github.com/bu5hm4nn/egui", rev = "521b087269acb6032d5040fa8bad33e84dbadede" }
|
||||
# Use the master branch of SDL2 to include a fix related to clang (and XCode after 14.2)
|
||||
sdl2 = { git = "https://github.com/Rust-SDL2/rust-sdl2", rev = "f2f1e29a416bcc22f2faf411866db2c8d9536308" }
|
||||
|
||||
|
@ -20,11 +20,11 @@ appimage = [ "gossip-lib/appimage" ]
|
||||
|
||||
[dependencies]
|
||||
bech32 = "0.11"
|
||||
eframe = { git = "https://github.com/bu5hm4nn/egui", rev = "63dde4c9b311da0cae0cb9f9465bf7273227be6c", features = [ "persistence", "wayland", "wgpu" ] }
|
||||
egui-winit = { git = "https://github.com/bu5hm4nn/egui", rev = "63dde4c9b311da0cae0cb9f9465bf7273227be6c", features = [ "default" ] }
|
||||
egui_extras = { git = "https://github.com/bu5hm4nn/egui", rev = "63dde4c9b311da0cae0cb9f9465bf7273227be6c", features = [ "syntect" ] }
|
||||
#egui = { git = "https://github.com/bu5hm4nn/egui", rev = "63dde4c9b311da0cae0cb9f9465bf7273227be6c", features = [ "deadlock_detection" ] }
|
||||
egui-video = { git = "https://github.com/mikedilger/egui-video", rev = "97f58f88dfe912697393567830d0751676492a89", features = [ "from_bytes" ], optional = true }
|
||||
eframe = { git = "https://github.com/bu5hm4nn/egui", rev = "521b087269acb6032d5040fa8bad33e84dbadede", features = [ "persistence", "wayland", "wgpu" ] }
|
||||
egui-winit = { git = "https://github.com/bu5hm4nn/egui", rev = "521b087269acb6032d5040fa8bad33e84dbadede", features = [ "default" ] }
|
||||
egui_extras = { git = "https://github.com/bu5hm4nn/egui", rev = "521b087269acb6032d5040fa8bad33e84dbadede", features = [ "syntect" ] }
|
||||
## egui = { git = "https://github.com/bu5hm4nn/egui", rev = "521b087269acb6032d5040fa8bad33e84dbadede", features = [ "deadlock_detection" ] }
|
||||
egui-video = { git = "https://github.com/bu5hm4nn/egui-video", rev = "21005df83139d0a7bdc910c66df3bc5a7b7bade2", features = [ "from_bytes" ], optional = true }
|
||||
gossip-relay-picker = { git = "https://github.com/mikedilger/gossip-relay-picker", rev = "3ea9ccfc641cdef1574a3c054a086ac2e24d3c4a" }
|
||||
gossip-lib = { path = "../gossip-lib" }
|
||||
humansize = "2.1"
|
||||
|
@ -160,7 +160,16 @@ pub(super) fn render_note(
|
||||
}
|
||||
|
||||
// Mark post as viewed if hovered AND we are not scrolling
|
||||
if !viewed && inner_response.response.hovered() && !app.is_scrolling() {
|
||||
if !viewed
|
||||
&& ui
|
||||
.interact(
|
||||
inner_response.response.rect,
|
||||
ui.next_auto_id().with("hov"),
|
||||
egui::Sense::hover(),
|
||||
)
|
||||
.hovered()
|
||||
&& !app.is_scrolling()
|
||||
{
|
||||
let _ = GLOBALS.storage.mark_event_viewed(id, None);
|
||||
}
|
||||
|
||||
@ -1305,7 +1314,7 @@ fn note_actions(
|
||||
.show(ui);
|
||||
let menu = widgets::MoreMenu::simple(ui.auto_id_with(note.event.id))
|
||||
.with_min_size(vec2(100.0, 0.0))
|
||||
.with_max_size(vec2(140.0, f32::INFINITY));
|
||||
.with_max_size(vec2(140.0, ui.ctx().available_rect().height()));
|
||||
let mut items: Vec<MoreMenuItem> = Vec::new();
|
||||
|
||||
// ---- Copy Text ----
|
||||
@ -1647,7 +1656,7 @@ fn draw_seen_on(app: &mut GossipUi, ui: &mut Ui, note: &std::cell::Ref<NoteData>
|
||||
let response = ui.add(Label::new(RichText::new("👁").size(12.0)).sense(Sense::hover()));
|
||||
|
||||
if response.hovered() {
|
||||
egui::Area::new(ui.next_auto_id())
|
||||
egui::Area::new(ui.next_auto_id().with("seen_on"))
|
||||
.movable(false)
|
||||
.interactable(false)
|
||||
// .pivot(Align2::RIGHT_TOP) // Fails to work as advertised
|
||||
|
@ -137,7 +137,7 @@ pub fn run() -> Result<(), Error> {
|
||||
if let Err(e) = eframe::run_native(
|
||||
"gossip",
|
||||
options,
|
||||
Box::new(|cc| Box::new(GossipUi::new(cc))),
|
||||
Box::new(|cc| Ok(Box::new(GossipUi::new(cc)))),
|
||||
) {
|
||||
tracing::error!("Eframe error: {}", e);
|
||||
}
|
||||
@ -1310,7 +1310,7 @@ impl GossipUi {
|
||||
+ Vec2::new(-crate::AVATAR_SIZE_F32 * 2.0, -crate::AVATAR_SIZE_F32 * 2.0)
|
||||
};
|
||||
|
||||
egui::Area::new(ui.next_auto_id())
|
||||
egui::Area::new(ui.next_auto_id().with("plus"))
|
||||
.movable(false)
|
||||
.interactable(true)
|
||||
.fixed_pos(pos)
|
||||
@ -1656,7 +1656,9 @@ impl GossipUi {
|
||||
|
||||
fn begin_ui(&self, ui: &mut Ui) {
|
||||
// if a dialog is open, disable the rest of the UI
|
||||
ui.set_enabled(self.enable_ui());
|
||||
if !self.enable_ui() {
|
||||
ui.disable();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn richtext_from_person_nip05(person: &Person) -> RichText {
|
||||
@ -2016,7 +2018,8 @@ impl GossipUi {
|
||||
|
||||
fn open_menu(&mut self, ctx: &Context, item: SubMenu) {
|
||||
for (submenu, id) in self.submenu_ids.iter() {
|
||||
let mut cstate = egui::CollapsingState::load_with_default_open(ctx, *id, false);
|
||||
let mut cstate =
|
||||
egui::collapsing_header::CollapsingState::load_with_default_open(ctx, *id, false);
|
||||
if item == SubMenu::Feeds || *submenu != SubMenu::Feeds {
|
||||
cstate.set_open(*submenu == item);
|
||||
}
|
||||
@ -2026,7 +2029,8 @@ impl GossipUi {
|
||||
|
||||
fn close_all_menus_except_feeds(&mut self, ctx: &Context) {
|
||||
for (submenu, id) in self.submenu_ids.iter() {
|
||||
let mut cstate = egui::CollapsingState::load_with_default_open(ctx, *id, false);
|
||||
let mut cstate =
|
||||
egui::collapsing_header::CollapsingState::load_with_default_open(ctx, *id, false);
|
||||
if *submenu != SubMenu::Feeds {
|
||||
cstate.set_open(false);
|
||||
}
|
||||
@ -2039,9 +2043,12 @@ impl GossipUi {
|
||||
ui: &mut Ui,
|
||||
ctx: &Context,
|
||||
submenu: SubMenu,
|
||||
) -> (egui::CollapsingState, Response) {
|
||||
let mut cstate =
|
||||
egui::CollapsingState::load_with_default_open(ctx, self.submenu_ids[&submenu], false);
|
||||
) -> (egui::collapsing_header::CollapsingState, Response) {
|
||||
let mut cstate = egui::collapsing_header::CollapsingState::load_with_default_open(
|
||||
ctx,
|
||||
self.submenu_ids[&submenu],
|
||||
false,
|
||||
);
|
||||
let open = cstate.is_open();
|
||||
let txt = if open {
|
||||
submenu.to_string() + " \u{25BE}"
|
||||
@ -2072,7 +2079,7 @@ impl GossipUi {
|
||||
(cstate, header_res.response)
|
||||
}
|
||||
|
||||
fn after_openable_menu(&self, ui: &mut Ui, cstate: &egui::CollapsingState) {
|
||||
fn after_openable_menu(&self, ui: &mut Ui, cstate: &egui::collapsing_header::CollapsingState) {
|
||||
if cstate.is_open() {
|
||||
ui.add_space(10.0)
|
||||
}
|
||||
|
@ -134,7 +134,9 @@ pub(super) fn update(
|
||||
});
|
||||
});
|
||||
|
||||
ui.set_enabled(enabled);
|
||||
if !enabled {
|
||||
ui.disable();
|
||||
}
|
||||
|
||||
ui.add_space(5.0);
|
||||
|
||||
@ -303,7 +305,10 @@ pub(super) fn update(
|
||||
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, f32::INFINITY));
|
||||
.with_max_size(vec2(
|
||||
100.0,
|
||||
ctx.available_rect().height(),
|
||||
));
|
||||
let mut items: Vec<MoreMenuItem> = Vec::new();
|
||||
|
||||
// actions
|
||||
@ -779,7 +784,7 @@ pub(super) fn render_more_list_actions(
|
||||
|
||||
let menu = widgets::MoreMenu::bubble(ui.next_auto_id())
|
||||
.with_min_size(vec2(100.0, 0.0))
|
||||
.with_max_size(vec2(140.0, f32::INFINITY));
|
||||
.with_max_size(vec2(140.0, ui.ctx().available_rect().height()));
|
||||
|
||||
let mut items: Vec<MoreMenuItem> = Vec::new();
|
||||
items.push(MoreMenuItem::Button(MoreMenuButton::new(
|
||||
|
@ -33,7 +33,9 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra
|
||||
});
|
||||
});
|
||||
|
||||
ui.set_enabled(enabled);
|
||||
if !enabled {
|
||||
ui.disable();
|
||||
}
|
||||
|
||||
let mut all_lists = GLOBALS
|
||||
.storage
|
||||
@ -109,13 +111,10 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra
|
||||
},
|
||||
);
|
||||
if row_response
|
||||
.response
|
||||
.inner
|
||||
.interact(Sense::click())
|
||||
.on_hover_cursor(egui::CursorIcon::PointingHand)
|
||||
.clicked()
|
||||
|| row_response
|
||||
.inner
|
||||
.on_hover_cursor(egui::CursorIcon::PointingHand)
|
||||
.clicked()
|
||||
{
|
||||
app.set_page(ctx, Page::PeopleList(list));
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use crate::ui::widgets::list_entry;
|
||||
use crate::ui::widgets::CopyButton;
|
||||
use crate::AVATAR_SIZE_F32;
|
||||
use eframe::egui::{self, Label};
|
||||
use eframe::epaint::PathStroke;
|
||||
use egui::{Context, RichText, TextEdit, Ui, Vec2};
|
||||
use egui_winit::egui::vec2;
|
||||
use egui_winit::egui::InnerResponse;
|
||||
@ -461,7 +462,7 @@ fn content(app: &mut GossipUi, ctx: &Context, ui: &mut Ui, pubkey: PublicKey, pe
|
||||
|
||||
// Right column, starting with avatar
|
||||
ui.allocate_ui_with_layout(
|
||||
vec2(AVATAR_COL_WIDTH, f32::INFINITY),
|
||||
vec2(AVATAR_COL_WIDTH, ui.ctx().available_rect().height()),
|
||||
egui::Layout::right_to_left(egui::Align::TOP).with_main_justify(true),
|
||||
|ui| {
|
||||
ui.vertical(|ui| {
|
||||
@ -618,7 +619,7 @@ fn profile_item(
|
||||
content: impl Into<String>,
|
||||
) {
|
||||
let content: String = content.into();
|
||||
let symbol = CopyButton::new().stroke(egui::Stroke::new(1.4, app.theme.accent_color()));
|
||||
let symbol = CopyButton::new().stroke(PathStroke::new(1.4, app.theme.accent_color()));
|
||||
let response = profile_item_frame(ui, width, label, &content, symbol).response;
|
||||
|
||||
if response.clicked() {
|
||||
@ -704,8 +705,8 @@ fn profile_item_frame(
|
||||
.response
|
||||
};
|
||||
|
||||
let frame_rect = (prepared.frame.inner_margin + prepared.frame.outer_margin)
|
||||
.expand_rect(prepared.content_ui.min_rect());
|
||||
let frame_rect = prepared.content_ui.min_rect()
|
||||
+ (prepared.frame.inner_margin + prepared.frame.outer_margin);
|
||||
|
||||
let response = ui
|
||||
.interact(frame_rect, ui.auto_id_with(&label), egui::Sense::click())
|
||||
|
@ -13,7 +13,9 @@ use nostr_types::RelayUrl;
|
||||
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| {
|
||||
ui.set_enabled(!is_editing);
|
||||
if is_editing {
|
||||
ui.disable();
|
||||
}
|
||||
super::configure_list_btn(app, ui);
|
||||
btn_h_space!(ui);
|
||||
super::relay_filter_combo(app, ui);
|
||||
|
@ -9,7 +9,9 @@ use gossip_lib::GLOBALS;
|
||||
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::RelaysKnownNetwork(None).name(), |ui| {
|
||||
ui.set_enabled(!is_editing);
|
||||
if is_editing {
|
||||
ui.disable();
|
||||
}
|
||||
super::configure_list_btn(app, ui);
|
||||
btn_h_space!(ui);
|
||||
super::relay_filter_combo(app, ui);
|
||||
|
@ -11,7 +11,9 @@ use std::sync::atomic::Ordering;
|
||||
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::RelaysMine.name(), |ui| {
|
||||
ui.set_enabled(!is_editing);
|
||||
if is_editing {
|
||||
ui.disable();
|
||||
}
|
||||
super::configure_list_btn(app, ui);
|
||||
btn_h_space!(ui);
|
||||
super::relay_filter_combo(app, ui);
|
||||
|
@ -293,7 +293,7 @@ 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("hide-background-area")
|
||||
egui::Area::new(Id::new("hide-background-area"))
|
||||
.fixed_pos(ctx.screen_rect().left_top())
|
||||
.movable(false)
|
||||
.interactable(false)
|
||||
@ -313,11 +313,6 @@ pub(super) fn entry_dialog(ctx: &Context, app: &mut GossipUi) {
|
||||
.interactable(true)
|
||||
.order(egui::Order::Foreground)
|
||||
.fixed_pos(ctx.screen_rect().center() - vec2(dlg_size.x / 2.0, dlg_size.y));
|
||||
area.show_open_close_animation(
|
||||
ctx,
|
||||
&frame,
|
||||
app.relays.add_dialog_step != AddRelayDialogStep::Inactive,
|
||||
);
|
||||
area.show(ctx, |ui| {
|
||||
frame.fill = ui.visuals().extreme_bg_color;
|
||||
frame.inner_margin = egui::Margin::symmetric(20.0, 10.0);
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::{NoteRenderData, ThemeDef};
|
||||
use crate::ui::HighlightType;
|
||||
use eframe::egui::style::{Selection, WidgetVisuals, Widgets};
|
||||
use eframe::egui::style::{Selection, TextCursorStyle, WidgetVisuals, Widgets};
|
||||
use eframe::egui::{
|
||||
vec2, FontDefinitions, Margin, Pos2, RichText, Shape, Stroke, Style, TextFormat, TextStyle,
|
||||
Vec2, Visuals,
|
||||
@ -28,14 +28,18 @@ pub trait ShadowBuilder {
|
||||
impl ShadowBuilder for Shadow {
|
||||
fn soft_dark() -> Self {
|
||||
Self {
|
||||
extrusion: 30.0,
|
||||
offset: vec2(6.0, 10.0),
|
||||
blur: 30.0,
|
||||
spread: 0.0,
|
||||
color: Color32::from_black_alpha(40),
|
||||
}
|
||||
}
|
||||
|
||||
fn soft_light() -> Self {
|
||||
Self {
|
||||
extrusion: 30.0,
|
||||
offset: vec2(6.0, 10.0),
|
||||
blur: 30.0,
|
||||
spread: 0.0,
|
||||
color: Color32::from_black_alpha(10),
|
||||
}
|
||||
}
|
||||
@ -284,8 +288,8 @@ impl ThemeDef for DefaultTheme {
|
||||
stroke: Stroke::new(0.0, Color32::from_gray(220)),
|
||||
},
|
||||
|
||||
window_shadow: Shadow::big_dark(),
|
||||
popup_shadow: Shadow::soft_dark(),
|
||||
window_shadow: Visuals::dark().window_shadow,
|
||||
popup_shadow: Visuals::dark().popup_shadow,
|
||||
|
||||
indent_has_left_vline: false,
|
||||
menu_rounding: Rounding::same(2.0),
|
||||
@ -295,8 +299,12 @@ impl ThemeDef for DefaultTheme {
|
||||
window_rounding: Rounding::same(6.0),
|
||||
window_highlight_topmost: false,
|
||||
resize_corner_size: 12.0,
|
||||
text_cursor: Stroke::new(2.0, Color32::from_rgb(192, 222, 255)),
|
||||
text_cursor_preview: false,
|
||||
|
||||
text_cursor: TextCursorStyle {
|
||||
stroke: Stroke::new(2.0, Color32::from_rgb(192, 222, 255)),
|
||||
preview: false,
|
||||
..Default::default()
|
||||
},
|
||||
clip_rect_margin: 3.0, // should be at least half the size of the widest frame stroke + max WidgetVisuals::expansion
|
||||
button_frame: true,
|
||||
collapsing_header_frame: false,
|
||||
@ -372,8 +380,8 @@ impl ThemeDef for DefaultTheme {
|
||||
stroke: Stroke::new(1.0, Color32::from_gray(40)), // DONE
|
||||
},
|
||||
|
||||
window_shadow: Shadow::big_light(),
|
||||
popup_shadow: Shadow::soft_light(),
|
||||
window_shadow: Visuals::light().window_shadow,
|
||||
popup_shadow: Visuals::light().popup_shadow,
|
||||
|
||||
indent_has_left_vline: false,
|
||||
menu_rounding: Rounding::same(2.0),
|
||||
@ -383,8 +391,11 @@ impl ThemeDef for DefaultTheme {
|
||||
window_rounding: Rounding::same(6.0),
|
||||
window_highlight_topmost: false,
|
||||
resize_corner_size: 12.0,
|
||||
text_cursor: Stroke::new(2.0, Color32::from_rgb(0, 83, 125)),
|
||||
text_cursor_preview: false,
|
||||
text_cursor: TextCursorStyle {
|
||||
stroke: Stroke::new(2.0, Color32::from_rgb(0, 83, 125)),
|
||||
preview: false,
|
||||
..Default::default()
|
||||
},
|
||||
clip_rect_margin: 3.0, // should be at least half the size of the widest frame stroke + max WidgetVisuals::expansion
|
||||
button_frame: true,
|
||||
collapsing_header_frame: false,
|
||||
|
@ -414,7 +414,7 @@ fn textedit_test(app: &mut GossipUi, ui: &mut Ui) {
|
||||
ui.add_space(20.0);
|
||||
ui.horizontal(|ui| {
|
||||
ui.add_sized(CSIZE, egui::Label::new("Disabled"));
|
||||
ui.set_enabled(false);
|
||||
ui.disable();
|
||||
ui.add_space(20.0);
|
||||
ui.vertical(|ui| {
|
||||
widgets::TextEdit::singleline(theme, &mut app.theme_test.textedit_empty)
|
||||
@ -477,7 +477,7 @@ fn switch_test(app: &mut GossipUi, ui: &mut Ui) {
|
||||
ui.add_space(20.0);
|
||||
ui.horizontal(|ui| {
|
||||
ui.add_sized(CSIZE, egui::Label::new("Disabled"));
|
||||
ui.set_enabled(false);
|
||||
ui.disable();
|
||||
ui.add_space(20.0);
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
|
@ -234,7 +234,7 @@ impl Button<'_> {
|
||||
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click());
|
||||
response.widget_info(|| {
|
||||
if let Some(text) = text {
|
||||
WidgetInfo::labeled(WidgetType::Button, text.text())
|
||||
WidgetInfo::labeled(WidgetType::Button, ui.is_enabled(), text.text())
|
||||
} else {
|
||||
WidgetInfo::new(WidgetType::Button)
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ pub(in crate::ui) fn show_contact_search(
|
||||
let frame = egui::Frame::popup(ui.style())
|
||||
.rounding(egui::Rounding::ZERO)
|
||||
.inner_margin(egui::Margin::same(0.0));
|
||||
let area = egui::Area::new(ui.next_auto_id())
|
||||
let area = egui::Area::new(ui.next_auto_id().with("tt"))
|
||||
.pivot(pivot)
|
||||
.fixed_pos(fixed_pos)
|
||||
.movable(false)
|
||||
@ -74,9 +74,8 @@ pub(in crate::ui) fn show_contact_search(
|
||||
prepared.content_ui.set_max_width(super::TAGG_WIDTH);
|
||||
prepared.content_ui.set_min_height(27.0);
|
||||
|
||||
let frame_rect = (prepared.frame.inner_margin
|
||||
+ prepared.frame.outer_margin)
|
||||
.expand_rect(prepared.content_ui.min_rect());
|
||||
let frame_rect = prepared.content_ui.min_rect()
|
||||
+ (prepared.frame.inner_margin + prepared.frame.outer_margin);
|
||||
|
||||
let response = ui
|
||||
.interact(
|
||||
@ -160,8 +159,6 @@ pub(in crate::ui) fn show_contact_search(
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
area.show_open_close_animation(ui.ctx(), &frame, is_open);
|
||||
}
|
||||
|
||||
pub(in crate::ui) fn capture_keyboard_for_search(
|
||||
|
@ -1,11 +1,14 @@
|
||||
use eframe::{egui, epaint};
|
||||
use eframe::{
|
||||
egui,
|
||||
epaint::{self, ColorMode, PathStroke},
|
||||
};
|
||||
use egui::{Color32, Pos2, Response, Sense, Shape, Ui, Vec2, Widget};
|
||||
use epaint::{PathShape, Stroke};
|
||||
use epaint::PathShape;
|
||||
|
||||
pub const COPY_SYMBOL_SIZE: Vec2 = Vec2::new(12.0, 12.0);
|
||||
|
||||
pub struct CopyButton {
|
||||
stroke: Option<Stroke>,
|
||||
stroke: Option<PathStroke>,
|
||||
}
|
||||
|
||||
impl CopyButton {
|
||||
@ -13,7 +16,7 @@ impl CopyButton {
|
||||
Self { stroke: None }
|
||||
}
|
||||
|
||||
pub(crate) fn stroke(mut self, stroke: Stroke) -> Self {
|
||||
pub(crate) fn stroke(mut self, stroke: PathStroke) -> Self {
|
||||
self.stroke = Some(stroke);
|
||||
self
|
||||
}
|
||||
@ -44,10 +47,14 @@ impl CopyButton {
|
||||
],
|
||||
closed: false,
|
||||
fill: Color32::TRANSPARENT,
|
||||
stroke: self.stroke.unwrap_or(Stroke {
|
||||
width: 1.0,
|
||||
color: Color32::from_rgb(0x8d, 0x7f, 0x73),
|
||||
}),
|
||||
stroke: if let Some(stroke) = &self.stroke {
|
||||
stroke.clone()
|
||||
} else {
|
||||
PathStroke {
|
||||
width: 1.0,
|
||||
color: ColorMode::Solid(Color32::from_rgb(0x8d, 0x7f, 0x73)),
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
ui.painter().add(Shape::Path(PathShape {
|
||||
@ -75,10 +82,14 @@ impl CopyButton {
|
||||
],
|
||||
closed: true,
|
||||
fill: Color32::TRANSPARENT,
|
||||
stroke: self.stroke.unwrap_or(Stroke {
|
||||
width: 1.0,
|
||||
color: Color32::from_rgb(0x8d, 0x7f, 0x73),
|
||||
}),
|
||||
stroke: if let Some(stroke) = &self.stroke {
|
||||
stroke.clone()
|
||||
} else {
|
||||
PathStroke {
|
||||
width: 1.0,
|
||||
color: ColorMode::Solid(Color32::from_rgb(0x8d, 0x7f, 0x73)),
|
||||
}
|
||||
},
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -43,14 +43,12 @@ pub(crate) fn paint_frame(ui: &mut Ui, rect: &Rect, fill: Option<Color32>) {
|
||||
rect.max - vec2(OUTER_MARGIN_RIGHT, OUTER_MARGIN_BOTTOM),
|
||||
);
|
||||
let fill = fill.unwrap_or(ui.visuals().extreme_bg_color);
|
||||
ui.painter().add(epaint::RectShape {
|
||||
rect: frame_rect,
|
||||
rounding: Rounding::same(5.0),
|
||||
ui.painter().add(epaint::RectShape::new(
|
||||
frame_rect,
|
||||
Rounding::same(5.0),
|
||||
fill,
|
||||
stroke: Stroke::NONE,
|
||||
fill_texture_id: Default::default(),
|
||||
uv: Rect::ZERO,
|
||||
});
|
||||
Stroke::NONE,
|
||||
));
|
||||
}
|
||||
|
||||
pub(crate) fn make_frame(ui: &Ui, fill: Option<Color32>) -> Frame {
|
||||
|
@ -74,9 +74,6 @@ pub fn modal_popup(
|
||||
.constrain(true)
|
||||
.order(egui::Order::Middle)
|
||||
.anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0]);
|
||||
area.show_open_close_animation(
|
||||
ctx, &frame, true, // TODO if we never pass false it won't show a close animation
|
||||
);
|
||||
area.show(ctx, |ui| {
|
||||
if ui.visuals().dark_mode {
|
||||
frame.fill = ui.visuals().faint_bg_color;
|
||||
@ -149,9 +146,6 @@ pub fn modal_popup_dyn(
|
||||
.constrain(true)
|
||||
.order(egui::Order::Middle)
|
||||
.anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0]);
|
||||
area.show_open_close_animation(
|
||||
ctx, &frame, true, // TODO if we never pass false it won't show a close animation
|
||||
);
|
||||
let frame_response = area
|
||||
.show(ctx, |ui| {
|
||||
if ui.visuals().dark_mode {
|
||||
|
@ -66,7 +66,9 @@ impl<'a> MoreMenuButton<'a> {
|
||||
}
|
||||
|
||||
fn show(self, app: &mut GossipUi, ui: &mut Ui) -> Response {
|
||||
ui.set_enabled(self.enabled);
|
||||
if !self.enabled {
|
||||
ui.disable();
|
||||
}
|
||||
|
||||
let response = draw_menu_button(ui, &app.theme, self.text, None);
|
||||
|
||||
@ -132,7 +134,9 @@ impl<'a> MoreMenuSubMenu<'a> {
|
||||
}
|
||||
|
||||
fn show(self, app: &mut GossipUi, ui: &mut Ui) -> Response {
|
||||
ui.set_enabled(self.enabled);
|
||||
if !self.enabled {
|
||||
ui.disable();
|
||||
}
|
||||
|
||||
let mut open = load_state(ui, &self.id);
|
||||
|
||||
@ -717,7 +721,7 @@ fn draw_menu_button(
|
||||
|
||||
// interact
|
||||
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click());
|
||||
response.widget_info(|| WidgetInfo::labeled(WidgetType::Button, title.text()));
|
||||
response.widget_info(|| WidgetInfo::labeled(WidgetType::Button, ui.is_enabled(), title.text()));
|
||||
let state = super::interact_widget_state(ui, &response);
|
||||
let state = match state {
|
||||
super::WidgetState::Default => {
|
||||
|
@ -16,6 +16,8 @@ use egui::*;
|
||||
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
|
||||
pub struct NavItem {
|
||||
text: WidgetText,
|
||||
wrap: Option<bool>,
|
||||
truncate: bool,
|
||||
sense: Option<Sense>,
|
||||
color: Option<Color32>,
|
||||
active_color: Option<Color32>,
|
||||
@ -27,6 +29,8 @@ impl NavItem {
|
||||
pub fn new(text: impl Into<WidgetText>, active: bool) -> Self {
|
||||
Self {
|
||||
text: text.into(),
|
||||
wrap: None,
|
||||
truncate: false,
|
||||
sense: None,
|
||||
color: None,
|
||||
active_color: None,
|
||||
@ -56,6 +60,42 @@ impl NavItem {
|
||||
self
|
||||
}
|
||||
|
||||
/// If `true`, the text will wrap to stay within the max width of the [`Ui`].
|
||||
///
|
||||
/// Calling `wrap` will override [`Self::truncate`].
|
||||
///
|
||||
/// By default [`Self::wrap`] will be `true` in vertical layouts
|
||||
/// and horizontal layouts with wrapping,
|
||||
/// and `false` on non-wrapping horizontal layouts.
|
||||
///
|
||||
/// Note that any `\n` in the text will always produce a new line.
|
||||
///
|
||||
/// You can also use [`crate::Style::wrap`].
|
||||
#[inline]
|
||||
#[allow(unused)]
|
||||
pub fn wrap(mut self, wrap: bool) -> Self {
|
||||
self.wrap = Some(wrap);
|
||||
self.truncate = false;
|
||||
self
|
||||
}
|
||||
|
||||
/// If `true`, the text will stop at the max width of the [`Ui`],
|
||||
/// and what doesn't fit will be elided, replaced with `…`.
|
||||
///
|
||||
/// If the text is truncated, the full text will be shown on hover as a tool-tip.
|
||||
///
|
||||
/// Default is `false`, which means the text will expand the parent [`Ui`],
|
||||
/// or wrap if [`Self::wrap`] is set.
|
||||
///
|
||||
/// Calling `truncate` will override [`Self::wrap`].
|
||||
#[inline]
|
||||
#[allow(unused)]
|
||||
pub fn truncate(mut self, truncate: bool) -> Self {
|
||||
self.wrap = None;
|
||||
self.truncate = truncate;
|
||||
self
|
||||
}
|
||||
|
||||
/// Make the label respond to clicks and/or drags.
|
||||
///
|
||||
/// By default, a label is inert and does not respond to click or drags.
|
||||
@ -79,7 +119,15 @@ impl NavItem {
|
||||
impl NavItem {
|
||||
/// Do layout and position the galley in the ui, without painting it or adding widget info.
|
||||
pub fn layout_in_ui(self, ui: &mut Ui) -> (Pos2, Arc<Galley>, Response) {
|
||||
let sense = self.sense.unwrap_or(Sense::click());
|
||||
let sense = self.sense.unwrap_or_else(|| {
|
||||
if ui.memory(|mem| mem.options.screen_reader) {
|
||||
// We only want to focus labels if the screen reader is on.
|
||||
Sense::focusable_noninteractive()
|
||||
} else {
|
||||
Sense::hover()
|
||||
}
|
||||
});
|
||||
|
||||
if let WidgetText::Galley(galley) = self.text {
|
||||
// If the user said "use this specific galley", then just use it:
|
||||
let (rect, response) = ui.allocate_exact_size(galley.size(), sense);
|
||||
@ -92,14 +140,18 @@ impl NavItem {
|
||||
}
|
||||
|
||||
let valign = ui.layout().vertical_align();
|
||||
let mut job = self
|
||||
let mut layout_job = self
|
||||
.text
|
||||
.into_layout_job(ui.style(), FontSelection::Default, valign);
|
||||
|
||||
let should_wrap = ui.wrap_text();
|
||||
let truncate = self.truncate;
|
||||
let wrap = !truncate
|
||||
&& self
|
||||
.wrap
|
||||
.unwrap_or_else(|| ui.wrap_mode() == TextWrapMode::Wrap);
|
||||
let available_width = ui.available_width();
|
||||
|
||||
if should_wrap
|
||||
if wrap
|
||||
&& ui.layout().main_dir() == Direction::LeftToRight
|
||||
&& ui.layout().main_wrap()
|
||||
&& available_width.is_finite()
|
||||
@ -109,29 +161,19 @@ impl NavItem {
|
||||
|
||||
let cursor = ui.cursor();
|
||||
let first_row_indentation = available_width - ui.available_size_before_wrap().x;
|
||||
egui_assert!(first_row_indentation.is_finite());
|
||||
debug_assert!(first_row_indentation.is_finite());
|
||||
|
||||
job.wrap.max_width = available_width;
|
||||
job.first_row_min_height = cursor.height();
|
||||
job.halign = Align::Min;
|
||||
job.justify = false;
|
||||
if let Some(first_section) = job.sections.first_mut() {
|
||||
layout_job.wrap.max_width = available_width;
|
||||
layout_job.first_row_min_height = cursor.height();
|
||||
layout_job.halign = Align::Min;
|
||||
layout_job.justify = false;
|
||||
if let Some(first_section) = layout_job.sections.first_mut() {
|
||||
first_section.leading_space = first_row_indentation;
|
||||
}
|
||||
let galley = ui.fonts(|f| f.layout_job(job));
|
||||
let galley = ui.fonts(|fonts| fonts.layout_job(layout_job));
|
||||
|
||||
let pos = pos2(ui.max_rect().left(), ui.cursor().top());
|
||||
assert!(!galley.rows.is_empty(), "Galleys are never empty");
|
||||
|
||||
// set the row height to ensure the cursor advancement is correct. when creating a child ui such as with
|
||||
// ui.horizontal_wrapped, the initial cursor will be set to the height of the child ui. this can lead
|
||||
// to the cursor not advancing to the second row but rather expanding the height of the cursor.
|
||||
//
|
||||
// note that we do not set the row height earlier in this function as we do want to allow populating
|
||||
// `first_row_min_height` above. however it is crucial the placer knows the actual row height by
|
||||
// setting the cursor height before ui.allocate_rect() gets called.
|
||||
ui.set_row_height(galley.rows[0].height());
|
||||
|
||||
// collect a response from many rows:
|
||||
let rect = galley.rows[0].rect.translate(vec2(pos.x, pos.y));
|
||||
let mut response = ui.allocate_rect(rect, sense);
|
||||
@ -141,23 +183,27 @@ impl NavItem {
|
||||
}
|
||||
(pos, galley, response)
|
||||
} else {
|
||||
if should_wrap {
|
||||
job.wrap.max_width = available_width;
|
||||
if truncate {
|
||||
layout_job.wrap.max_width = available_width;
|
||||
layout_job.wrap.max_rows = 1;
|
||||
layout_job.wrap.break_anywhere = true;
|
||||
} else if wrap {
|
||||
layout_job.wrap.max_width = available_width;
|
||||
} else {
|
||||
job.wrap.max_width = f32::INFINITY;
|
||||
layout_job.wrap.max_width = f32::INFINITY;
|
||||
};
|
||||
|
||||
job.halign = ui.layout().horizontal_placement();
|
||||
job.justify = ui.layout().horizontal_justify();
|
||||
layout_job.halign = ui.layout().horizontal_placement();
|
||||
layout_job.justify = ui.layout().horizontal_justify();
|
||||
|
||||
let galley = ui.fonts(|f| f.layout_job(job));
|
||||
let galley = ui.fonts(|fonts| fonts.layout_job(layout_job));
|
||||
let (rect, response) = ui.allocate_exact_size(galley.size(), sense);
|
||||
let pos = match galley.job.halign {
|
||||
let galley_pos = match galley.job.halign {
|
||||
Align::LEFT => rect.left_top(),
|
||||
Align::Center => rect.center_top(),
|
||||
Align::RIGHT => rect.right_top(),
|
||||
};
|
||||
(pos, galley, response)
|
||||
(galley_pos, galley, response)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,7 +215,8 @@ impl Widget for NavItem {
|
||||
let hover_color = self.hover_color;
|
||||
let active_color = self.active_color;
|
||||
let (pos, galley, response) = self.layout_in_ui(ui);
|
||||
response.widget_info(|| WidgetInfo::labeled(WidgetType::Label, galley.text()));
|
||||
response
|
||||
.widget_info(|| WidgetInfo::labeled(WidgetType::Label, ui.is_enabled(), galley.text()));
|
||||
|
||||
if ui.is_rect_visible(response.rect) {
|
||||
let color = if hover_color.is_some() && response.hovered() {
|
||||
|
@ -357,7 +357,7 @@ impl RelayEntry {
|
||||
let button_padding = ui.spacing().button_padding;
|
||||
let galley = WidgetText::from("Close")
|
||||
.color(ui.visuals().extreme_bg_color)
|
||||
.into_galley(ui, Some(false), 0.0, TextStyle::Button);
|
||||
.into_galley(ui, Some(TextWrapMode::Extend), 0.0, TextStyle::Button);
|
||||
let mut desired_size = galley.size() + 4.0 * button_padding;
|
||||
desired_size.y = desired_size.y.at_least(ui.spacing().interact_size.y);
|
||||
let pos = rect.right_bottom() + vec2(-TEXT_RIGHT, -TEXT_BOTTOM) - desired_size;
|
||||
@ -365,7 +365,9 @@ impl RelayEntry {
|
||||
let response = ui
|
||||
.interact(btn_rect, id, Sense::click())
|
||||
.on_hover_cursor(egui::CursorIcon::PointingHand);
|
||||
response.widget_info(|| WidgetInfo::labeled(WidgetType::Button, galley.text()));
|
||||
response.widget_info(|| {
|
||||
WidgetInfo::labeled(WidgetType::Button, ui.is_enabled(), galley.text())
|
||||
});
|
||||
|
||||
let visuals = ui.style().interact(&response);
|
||||
{
|
||||
|
@ -75,7 +75,12 @@ impl<'a> Switch<'a> {
|
||||
fn allocate(&mut self, ui: &mut Ui) -> (Response, Option<Arc<Galley>>) {
|
||||
let (extra_width, galley) = if let Some(text) = self.label.take() {
|
||||
let available_width = ui.available_width() - self.size.y - ui.spacing().item_spacing.y;
|
||||
let galley = text.into_galley(ui, Some(false), available_width, TextStyle::Body);
|
||||
let galley = text.into_galley(
|
||||
ui,
|
||||
Some(egui::TextWrapMode::Truncate),
|
||||
available_width,
|
||||
TextStyle::Body,
|
||||
);
|
||||
(
|
||||
galley.rect.width() + ui.spacing().item_spacing.y,
|
||||
Some(galley),
|
||||
@ -136,7 +141,9 @@ pub fn switch_custom_at(
|
||||
} else {
|
||||
response
|
||||
};
|
||||
response.widget_info(|| egui::WidgetInfo::selected(egui::WidgetType::Checkbox, *value, ""));
|
||||
response.widget_info(|| {
|
||||
egui::WidgetInfo::selected(egui::WidgetType::Checkbox, ui.is_enabled(), *value, "")
|
||||
});
|
||||
|
||||
if ui.is_rect_visible(rect) {
|
||||
let how_on = ui.ctx().animate_bool(response.id, *value);
|
||||
@ -204,7 +211,12 @@ fn interact(
|
||||
|
||||
let text = label.unwrap_or("".into());
|
||||
response.widget_info(|| {
|
||||
egui::WidgetInfo::selected(egui::WidgetType::Checkbox, *value, text.text())
|
||||
egui::WidgetInfo::selected(
|
||||
egui::WidgetType::Checkbox,
|
||||
ui.is_enabled(),
|
||||
*value,
|
||||
text.text(),
|
||||
)
|
||||
});
|
||||
|
||||
(state, response)
|
||||
|
@ -1,3 +1,4 @@
|
||||
use eframe::egui::style::TextCursorStyle;
|
||||
use egui_winit::egui::{
|
||||
self, load::SizedTexture, vec2, Color32, Rect, Rounding, Sense, Stroke, TextBuffer,
|
||||
TextureHandle, Widget, WidgetText,
|
||||
@ -161,7 +162,7 @@ impl<'t> TextEdit<'t> {
|
||||
{
|
||||
let theme = self.theme;
|
||||
let response = &output.response;
|
||||
let frame_rect = response.rect;
|
||||
let frame_rect = response.rect + margin;
|
||||
|
||||
// this is how egui chooses the visual style:
|
||||
#[allow(clippy::if_same_then_else)]
|
||||
@ -290,7 +291,10 @@ impl TextEdit<'_> {
|
||||
let visuals = ui.visuals_mut();
|
||||
|
||||
// cursor (enabled)
|
||||
visuals.text_cursor = Stroke::new(3.0, theme.accent_color());
|
||||
visuals.text_cursor = TextCursorStyle {
|
||||
stroke: Stroke::new(3.0, theme.accent_color()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
if visuals.dark_mode {
|
||||
// text color (enabled)
|
||||
|
@ -177,7 +177,10 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, _frame: &mut eframe::Fra
|
||||
ui.label("or");
|
||||
ui.menu_button("▼ Pick from Top Relays", |ui| {
|
||||
for (url, _relay) in relay_options.iter() {
|
||||
if ui.add(Button::new(url.as_str()).wrap(false)).clicked() {
|
||||
if ui
|
||||
.add(Button::new(url.as_str()).wrap_mode(egui::TextWrapMode::Extend))
|
||||
.clicked()
|
||||
{
|
||||
app.wizard_state.relay_url = url.as_str().to_owned();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
use super::{GossipUi, Page};
|
||||
use crate::ui::widgets::CopyButton;
|
||||
use eframe::egui;
|
||||
use egui::style::Margin;
|
||||
use eframe::egui::{self, Margin};
|
||||
use egui::{Color32, Context, Frame, Stroke, Ui};
|
||||
use gossip_lib::comms::ToOverlordMessage;
|
||||
use gossip_lib::{Globals, GLOBALS};
|
||||
|
Loading…
Reference in New Issue
Block a user