ui: add list item button
This commit is contained in:
parent
b6e55b0762
commit
a31d38dc1c
3 changed files with 151 additions and 69 deletions
|
@ -36,4 +36,5 @@ impl Colors {
|
||||||
pub const STROKE: Color32 = Color32::from_gray(190);
|
pub const STROKE: Color32 = Color32::from_gray(190);
|
||||||
pub const INACTIVE_TEXT: Color32 = Color32::from_gray(150);
|
pub const INACTIVE_TEXT: Color32 = Color32::from_gray(150);
|
||||||
pub const ITEM_STROKE: Color32 = Color32::from_gray(220);
|
pub const ITEM_STROKE: Color32 = Color32::from_gray(220);
|
||||||
|
pub const ITEM_HOVER_STROKE: Color32 = Color32::from_gray(205);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use egui::{Id, RichText, Rounding, TextStyle, Ui, Widget};
|
use egui::{Align, Id, Layout, RichText, Rounding, TextStyle, Ui, Widget};
|
||||||
use egui_extras::{Size, StripBuilder};
|
use egui_extras::{Size, StripBuilder};
|
||||||
use grin_core::global::ChainTypes;
|
use grin_core::global::ChainTypes;
|
||||||
|
|
||||||
|
@ -474,58 +474,96 @@ impl P2PSetup {
|
||||||
|
|
||||||
/// Draw peer list item.
|
/// Draw peer list item.
|
||||||
fn peer_item_ui(ui: &mut Ui, peer_addr: &String, peer_type: &PeerType, rounding: Rounding) {
|
fn peer_item_ui(ui: &mut Ui, peer_addr: &String, peer_type: &PeerType, rounding: Rounding) {
|
||||||
// Draw round background.
|
// Setup layout size.
|
||||||
let mut rect = ui.available_rect_before_wrap();
|
let mut rect = ui.available_rect_before_wrap();
|
||||||
rect.min += egui::emath::vec2(6.0, 0.0);
|
|
||||||
rect.set_height(42.0);
|
rect.set_height(42.0);
|
||||||
ui.painter().rect(rect, rounding, Colors::WHITE, View::ITEM_STROKE);
|
|
||||||
|
|
||||||
StripBuilder::new(ui)
|
// Draw round background.
|
||||||
.size(Size::exact(42.0))
|
let mut bg_rect = rect.clone();
|
||||||
.vertical(|mut strip| {
|
bg_rect.min += egui::emath::vec2(6.0, 0.0);
|
||||||
strip.strip(|builder| {
|
ui.painter().rect(bg_rect, rounding, Colors::WHITE, View::ITEM_STROKE);
|
||||||
builder
|
|
||||||
.size(Size::exact(13.0))
|
ui.vertical(|ui| {
|
||||||
.size(Size::remainder())
|
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
|
||||||
.size(Size::exact(46.0))
|
// Draw delete button for non-default seed peers.
|
||||||
.horizontal(|mut strip| {
|
if peer_type != &PeerType::DefaultSeed {
|
||||||
strip.empty();
|
View::item_button(ui, [false, true], TRASH, || {
|
||||||
strip.cell(|ui| {
|
match peer_type {
|
||||||
ui.horizontal_centered(|ui| {
|
PeerType::CustomSeed => {
|
||||||
// Draw peer address.
|
NodeConfig::remove_custom_seed(peer_addr);
|
||||||
let peer_text = format!("{} {}", COMPUTER_TOWER, &peer_addr);
|
|
||||||
ui.label(RichText::new(peer_text)
|
|
||||||
.color(Colors::TEXT_BUTTON)
|
|
||||||
.size(16.0));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
if peer_type != &PeerType::DefaultSeed {
|
|
||||||
strip.cell(|ui| {
|
|
||||||
// Draw delete button for non-default seed peers.
|
|
||||||
View::button(ui, TRASH.to_string(), Colors::BUTTON, || {
|
|
||||||
match peer_type {
|
|
||||||
PeerType::CustomSeed => {
|
|
||||||
NodeConfig::remove_custom_seed(peer_addr);
|
|
||||||
}
|
|
||||||
PeerType::Allowed => {
|
|
||||||
NodeConfig::remove_allowed_peer(peer_addr);
|
|
||||||
}
|
|
||||||
PeerType::Denied => {
|
|
||||||
NodeConfig::remove_denied_peer(peer_addr);
|
|
||||||
}
|
|
||||||
PeerType::Preferred => {
|
|
||||||
NodeConfig::remove_preferred_peer(peer_addr);
|
|
||||||
}
|
|
||||||
PeerType::DefaultSeed => {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
strip.empty();
|
|
||||||
}
|
}
|
||||||
});
|
PeerType::Allowed => {
|
||||||
|
NodeConfig::remove_allowed_peer(peer_addr);
|
||||||
|
}
|
||||||
|
PeerType::Denied => {
|
||||||
|
NodeConfig::remove_denied_peer(peer_addr);
|
||||||
|
}
|
||||||
|
PeerType::Preferred => {
|
||||||
|
NodeConfig::remove_preferred_peer(peer_addr);
|
||||||
|
}
|
||||||
|
PeerType::DefaultSeed => {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let layout_size = ui.available_size();
|
||||||
|
ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| {
|
||||||
|
ui.add_space(12.0);
|
||||||
|
// Draw peer address.
|
||||||
|
let peer_text = format!("{} {}", COMPUTER_TOWER, &peer_addr);
|
||||||
|
ui.label(RichText::new(peer_text)
|
||||||
|
.color(Colors::TEXT_BUTTON)
|
||||||
|
.size(16.0));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// StripBuilder::new(ui)
|
||||||
|
// .size(Size::exact(42.0))
|
||||||
|
// .vertical(|mut strip| {
|
||||||
|
// strip.strip(|builder| {
|
||||||
|
// builder
|
||||||
|
// .size(Size::exact(13.0))
|
||||||
|
// .size(Size::remainder())
|
||||||
|
// .size(Size::exact(42.0))
|
||||||
|
// .horizontal(|mut strip| {
|
||||||
|
// strip.empty();
|
||||||
|
// strip.cell(|ui| {
|
||||||
|
// ui.horizontal_centered(|ui| {
|
||||||
|
// // Draw peer address.
|
||||||
|
// let peer_text = format!("{} {}", COMPUTER_TOWER, &peer_addr);
|
||||||
|
// ui.label(RichText::new(peer_text)
|
||||||
|
// .color(Colors::TEXT_BUTTON)
|
||||||
|
// .size(16.0));
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// if peer_type != &PeerType::DefaultSeed {
|
||||||
|
// strip.cell(|ui| {
|
||||||
|
// // Draw delete button for non-default seed peers.
|
||||||
|
// View::item_button(ui, [false, true], TRASH, || {
|
||||||
|
// match peer_type {
|
||||||
|
// PeerType::CustomSeed => {
|
||||||
|
// NodeConfig::remove_custom_seed(peer_addr);
|
||||||
|
// }
|
||||||
|
// PeerType::Allowed => {
|
||||||
|
// NodeConfig::remove_allowed_peer(peer_addr);
|
||||||
|
// }
|
||||||
|
// PeerType::Denied => {
|
||||||
|
// NodeConfig::remove_denied_peer(peer_addr);
|
||||||
|
// }
|
||||||
|
// PeerType::Preferred => {
|
||||||
|
// NodeConfig::remove_preferred_peer(peer_addr);
|
||||||
|
// }
|
||||||
|
// PeerType::DefaultSeed => {}
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// strip.empty();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw seeding type setup content.
|
/// Draw seeding type setup content.
|
||||||
|
|
|
@ -30,6 +30,8 @@ impl View {
|
||||||
pub const DEFAULT_STROKE: Stroke = Stroke { width: 1.0, color: Colors::STROKE };
|
pub const DEFAULT_STROKE: Stroke = Stroke { width: 1.0, color: Colors::STROKE };
|
||||||
/// Stroke around list items.
|
/// Stroke around list items.
|
||||||
pub const ITEM_STROKE: Stroke = Stroke { width: 1.0, color: Colors::ITEM_STROKE };
|
pub const ITEM_STROKE: Stroke = Stroke { width: 1.0, color: Colors::ITEM_STROKE };
|
||||||
|
/// Stroke around list items.
|
||||||
|
pub const ITEM_HOVER_STROKE: Stroke = Stroke { width: 1.0, color: Colors::ITEM_HOVER_STROKE };
|
||||||
|
|
||||||
/// Callback on Enter key press event.
|
/// Callback on Enter key press event.
|
||||||
pub fn on_enter_key(ui: &mut egui::Ui, cb: impl FnOnce()) {
|
pub fn on_enter_key(ui: &mut egui::Ui, cb: impl FnOnce()) {
|
||||||
|
@ -102,12 +104,16 @@ impl View {
|
||||||
/// Title button with transparent background fill color, contains only icon.
|
/// Title button with transparent background fill color, contains only icon.
|
||||||
pub fn title_button(ui: &mut egui::Ui, icon: &str, action: impl FnOnce()) {
|
pub fn title_button(ui: &mut egui::Ui, icon: &str, action: impl FnOnce()) {
|
||||||
ui.scope(|ui| {
|
ui.scope(|ui| {
|
||||||
// Disable stroke around title buttons on click.
|
// Setup stroke around title buttons on click.
|
||||||
ui.style_mut().visuals.widgets.active.bg_stroke = Stroke::NONE;
|
ui.style_mut().visuals.widgets.hovered.bg_stroke = Self::ITEM_HOVER_STROKE;
|
||||||
// Disable rounding on hover.
|
ui.style_mut().visuals.widgets.active.bg_stroke = Self::DEFAULT_STROKE;
|
||||||
|
// Disable rounding.
|
||||||
ui.style_mut().visuals.widgets.hovered.rounding = Rounding::none();
|
ui.style_mut().visuals.widgets.hovered.rounding = Rounding::none();
|
||||||
// Disable stroke color on hover.
|
ui.style_mut().visuals.widgets.active.rounding = Rounding::none();
|
||||||
ui.style_mut().visuals.widgets.hovered.bg_stroke = Self::DEFAULT_STROKE;
|
// Disable expansion.
|
||||||
|
ui.style_mut().visuals.widgets.hovered.expansion = 0.0;
|
||||||
|
ui.style_mut().visuals.widgets.active.expansion = 0.0;
|
||||||
|
|
||||||
// Setup text.
|
// Setup text.
|
||||||
let wt = RichText::new(icon.to_string()).size(22.0).color(Colors::TITLE);
|
let wt = RichText::new(icon.to_string()).size(22.0).color(Colors::TITLE);
|
||||||
// Draw button.
|
// Draw button.
|
||||||
|
@ -156,14 +162,12 @@ impl View {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw round [`Button`] with icon.
|
/// Draw round [`Button`] with icon.
|
||||||
pub fn round_button(ui: &mut egui::Ui,
|
pub fn round_button(ui: &mut egui::Ui, icon: &'static str, action: impl FnOnce()) {
|
||||||
icon: &'static str,
|
|
||||||
action: impl FnOnce()) {
|
|
||||||
ui.scope(|ui| {
|
ui.scope(|ui| {
|
||||||
// Setup colors.
|
// Setup colors.
|
||||||
ui.visuals_mut().widgets.inactive.bg_fill = Colors::BUTTON;
|
ui.visuals_mut().widgets.inactive.bg_fill = Colors::BUTTON;
|
||||||
ui.visuals_mut().widgets.hovered.bg_fill = Colors::GOLD;
|
ui.visuals_mut().widgets.hovered.bg_fill = Colors::FILL;
|
||||||
ui.visuals_mut().widgets.active.bg_fill = Colors::YELLOW;
|
ui.visuals_mut().widgets.active.bg_fill = Colors::FILL_DARK;
|
||||||
|
|
||||||
// Setup radius.
|
// Setup radius.
|
||||||
let mut r = 44.0 * 0.5;
|
let mut r = 44.0 * 0.5;
|
||||||
|
@ -174,7 +178,7 @@ impl View {
|
||||||
|
|
||||||
// Increase radius and change icon size and color on-hover.
|
// Increase radius and change icon size and color on-hover.
|
||||||
if br.hovered() {
|
if br.hovered() {
|
||||||
r = r * 1.07;
|
r = r * 1.05;
|
||||||
icon_color = Colors::TEXT_BUTTON;
|
icon_color = Colors::TEXT_BUTTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,24 +200,63 @@ impl View {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw list item [`Button`] with given vertical padding and rounding on left and right sides.
|
||||||
|
pub fn item_button(ui: &mut egui::Ui, r: [bool; 2], icon: &'static str, action: impl FnOnce()) {
|
||||||
|
let rounding = Self::get_rounding([r[0], r[1], r[1], r[0]]);
|
||||||
|
|
||||||
|
// Setup button size.
|
||||||
|
let mut rect = ui.available_rect_before_wrap();
|
||||||
|
rect.set_width(32.0);
|
||||||
|
let button_size = rect.size();
|
||||||
|
|
||||||
|
ui.scope(|ui| {
|
||||||
|
// Disable expansion on click/hover.
|
||||||
|
ui.style_mut().visuals.widgets.hovered.expansion = 0.0;
|
||||||
|
ui.style_mut().visuals.widgets.active.expansion = 0.0;
|
||||||
|
|
||||||
|
// Setup fill colors.
|
||||||
|
ui.visuals_mut().widgets.inactive.weak_bg_fill = Colors::WHITE;
|
||||||
|
ui.visuals_mut().widgets.hovered.weak_bg_fill = Colors::BUTTON;
|
||||||
|
ui.visuals_mut().widgets.active.weak_bg_fill = Colors::FILL;
|
||||||
|
|
||||||
|
// Setup stroke colors.
|
||||||
|
ui.visuals_mut().widgets.inactive.bg_stroke = Self::DEFAULT_STROKE;
|
||||||
|
ui.visuals_mut().widgets.hovered.bg_stroke = Self::ITEM_HOVER_STROKE;
|
||||||
|
ui.visuals_mut().widgets.active.bg_stroke = Self::ITEM_STROKE;
|
||||||
|
|
||||||
|
// Show button.
|
||||||
|
let br = Button::new(RichText::new(icon).size(20.0).color(Colors::CHECKBOX))
|
||||||
|
.rounding(rounding)
|
||||||
|
.min_size(button_size)
|
||||||
|
.ui(ui);
|
||||||
|
if Self::touched(ui, br) {
|
||||||
|
(action)();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get rounding for provided corners clockwise.
|
||||||
|
fn get_rounding(corners: [bool; 4]) -> Rounding {
|
||||||
|
Rounding {
|
||||||
|
nw: if corners[0] { 8.0 } else { 0.0 },
|
||||||
|
ne: if corners[1] { 8.0 } else { 0.0 },
|
||||||
|
sw: if corners[3] { 8.0 } else { 0.0 },
|
||||||
|
se: if corners[2] { 8.0 } else { 0.0 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculate list item rounding based on item index.
|
/// Calculate list item rounding based on item index.
|
||||||
pub fn item_rounding(index: usize, len: usize) -> Rounding {
|
pub fn item_rounding(index: usize, len: usize) -> Rounding {
|
||||||
let rounding = if len == 1 {
|
let rounding = if len == 1 {
|
||||||
[true, true]
|
[true, true, true, true]
|
||||||
} else if index == 0 {
|
} else if index == 0 {
|
||||||
[true, false]
|
[true, true, false, false]
|
||||||
} else if index == len - 1 {
|
} else if index == len - 1 {
|
||||||
[false, true]
|
[false, false, true, true]
|
||||||
} else {
|
} else {
|
||||||
[false, false]
|
[false, false, false, false]
|
||||||
};
|
};
|
||||||
|
Self::get_rounding(rounding)
|
||||||
Rounding {
|
|
||||||
nw: if rounding[0] { 8.0 } else { 0.0 },
|
|
||||||
ne: if rounding[0] { 8.0 } else { 0.0 },
|
|
||||||
sw: if rounding[1] { 8.0 } else { 0.0 },
|
|
||||||
se: if rounding[1] { 8.0 } else { 0.0 },
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw rounded box with some value and label in the middle,
|
/// Draw rounded box with some value and label in the middle,
|
||||||
|
|
Loading…
Reference in a new issue