-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable shortcut text independently of widget type, or add support to Checkbox #4363
Comments
Here's my version that is generic over the widget, but in 0.28.0 it seems to allocate horizontal too much space when used within a menu compared to the provided shortcut_text. I'm still trying to figure out how to layout the shortcut right-aligned similar to the Button implementation, but I'm not sure if it's possible while still using the provided pub trait ShortcutText<'a>
where
Self: Sized + 'a,
{
fn shortcut_text(self, shortcut_text: impl Into<WidgetText>) -> ShortcutWidget<'a, Self> {
ShortcutWidget {
inner: self,
shortcut_text: shortcut_text.into(),
phantom: std::marker::PhantomData,
}
}
}
impl<'a> ShortcutText<'a> for Checkbox<'a> {}
impl<'a> ShortcutText<'a> for ToggleValue<'a> {}
impl<'a, T> ShortcutText<'a> for RadioValue<'a, T> {}
#[must_use]
pub struct ShortcutWidget<'a, T> {
inner: T,
shortcut_text: WidgetText,
phantom: std::marker::PhantomData<&'a ()>,
}
impl<'a, T> Deref for ShortcutWidget<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a, T> DerefMut for ShortcutWidget<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<'a, T> Widget for ShortcutWidget<'a, T>
where
T: Widget,
{
fn ui(self, ui: &mut Ui) -> Response {
ui.horizontal(|ui| {
let res = self.inner.ui(ui);
if !self.shortcut_text.is_empty() {
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
// Ensure sense is set to hover so that screen readers don't try to read it,
// consistent with `shortcut_text` on `Button`
ui.add(egui::Label::new(self.shortcut_text.weak()).sense(egui::Sense::hover()));
});
}
res
})
.inner
}
}
#[must_use]
pub struct ToggleValue<'a> {
selected: &'a mut bool,
text: WidgetText,
}
impl<'a> ToggleValue<'a> {
pub fn new(selected: &'a mut bool, text: impl Into<WidgetText>) -> Self {
Self {
selected,
text: text.into(),
}
}
}
impl<'a> Widget for ToggleValue<'a> {
fn ui(self, ui: &mut Ui) -> Response {
let mut res = ui.selectable_label(*self.selected, self.text);
if res.clicked() {
*self.selected = !*self.selected;
res.mark_changed();
}
res
}
}
#[must_use]
pub struct RadioValue<'a, T> {
current_value: &'a mut T,
alternative: T,
text: WidgetText,
}
impl<'a, T: PartialEq> RadioValue<'a, T> {
pub fn new(current_value: &'a mut T, alternative: T, text: impl Into<WidgetText>) -> Self {
Self {
current_value,
alternative,
text: text.into(),
}
}
}
impl<'a, T: PartialEq> Widget for RadioValue<'a, T> {
fn ui(self, ui: &mut Ui) -> Response {
let mut res = ui.radio(*self.current_value == self.alternative, self.text);
if res.clicked() && *self.current_value != self.alternative {
*self.current_value = self.alternative;
res.mark_changed();
}
res
}
} |
This update seems to fix the width issue: ui.horizontal(|ui| {
let res = self.inner.ui(ui);
if !self.shortcut_text.is_empty() {
let shortcut_galley = self.shortcut_text.into_galley(
ui,
Some(TextWrapMode::Extend),
f32::INFINITY,
TextStyle::Button,
);
let available_rect = ui.available_rect_before_wrap();
let gap_before_shortcut_text = ui.spacing().item_spacing.x;
let mut desired_size = shortcut_galley.size();
desired_size.x += gap_before_shortcut_text;
// Ensure sense is set to hover so that screen readers don't try to read it,
// consistent with `shortcut_text` on `Button`
let (rect, _) = ui.allocate_at_least(desired_size, Sense::hover());
if ui.is_rect_visible(rect) {
let text_pos = Pos2::new(
available_rect.max.x - shortcut_galley.size().x,
rect.center().y - 0.5 * shortcut_galley.size().y,
);
ui.painter()
.galley(text_pos, shortcut_galley, ui.visuals().weak_text_color());
}
}
res
}) |
This is similar to #429 but without the complexity of actually implementing the shortcut functionality, only the text rendering part.
Is your feature request related to a problem? Please describe.
I need a togglable menu item to show or hide a panel. I'm using a
Checkbox
inside aMenu
. I want also a keyboard shortcut to be displayed on the right side, likeButton::shortcut_text
, but this is not implemented forCheckbox
, only forButton
.Describe the solution you'd like
Either of:
Checkbox::shortcut_text
(but there might be other widgets which also need that); orDescribe alternatives you've considered
I use this workaround which works fine, is just verbose and not super intuitive (some other issue suggested to use
Layout
instead ofUi::horizontal()
but this is wrong, as this will expand vertically the menu item to the entire screen; we need theLayout
to expand inside theHorizontal
so that it expands only horizontally (I think)):Note:
shortcut
here is Bevy'sKeycode
so will display the key name, like "F1" for example. But the solution works with any text I believe.Additional praise
This crate is awesome, thanks a lot for all the hard work, this is so useful! ❤️
The text was updated successfully, but these errors were encountered: