Browse Source

Add Link widget (#1506)

This looks like a Hyperlink, but doesn't do anything when clicked.
Or rather: it lets the user decide what happens on click.

Closes https://github.com/emilk/egui/issues/1152
pull/1512/head
Emil Ernerfeldt 3 years ago
committed by GitHub
parent
commit
2d2022fb72
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      CHANGELOG.md
  2. 2
      egui/src/data/output.rs
  3. 3
      egui/src/lib.rs
  4. 30
      egui/src/ui.rs
  5. 94
      egui/src/widgets/hyperlink.rs
  6. 6
      egui_demo_lib/src/apps/demo/widget_gallery.rs

3
CHANGELOG.md

@ -14,6 +14,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w
* Added `Ui::push_id` to resolve id clashes ([#1374](https://github.com/emilk/egui/pull/1374)).
* Added `Frame::outer_margin`.
* Added `Painter::hline` and `Painter::vline`.
* Added `Link` and `ui.link` ([#1506](https://github.com/emilk/egui/pull/1506)).
### Changed 🔧
* `ClippedMesh` has been replaced with `ClippedPrimitive` ([#1351](https://github.com/emilk/egui/pull/1351)).
@ -27,7 +28,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w
* Renamed the feature `serialize` to `serde` ([#1467](https://github.com/emilk/egui/pull/1467)).
### Fixed 🐛
* Fixed ComboBoxes always being rendered left-aligned ([#1304](https://github.com/emilk/egui/pull/1304)).
* Fixed `ComboBox`:es always being rendered left-aligned ([#1304](https://github.com/emilk/egui/pull/1304)).
* Fixed ui code that could lead to a deadlock ([#1380](https://github.com/emilk/egui/pull/1380)).
* Text is darker and more readable in bright mode ([#1412](https://github.com/emilk/egui/pull/1412)).
* Fixed `Ui::add_visible` sometimes leaving the `Ui` in a disabled state. ([#1436](https://github.com/emilk/egui/issues/1436)).

2
egui/src/data/output.rs

@ -466,7 +466,7 @@ impl WidgetInfo {
// TODO: localization
let widget_type = match typ {
WidgetType::Hyperlink => "link",
WidgetType::Link => "link",
WidgetType::TextEdit => "text edit",
WidgetType::Button => "button",
WidgetType::Checkbox => "checkbox",

3
egui/src/lib.rs

@ -494,7 +494,8 @@ pub mod special_emojis {
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum WidgetType {
Label, // TODO: emit Label events
Hyperlink,
/// e.g. a hyperlink
Link,
TextEdit,
Button,
Checkbox,

30
egui/src/ui.rs

@ -1227,14 +1227,40 @@ impl Ui {
Label::new(text.into().weak()).ui(self)
}
/// Shortcut for `add(Hyperlink::new(url))`
/// Looks like a hyperlink.
///
/// Shortcut for `add(Link::new(text))`.
///
/// ```
/// # egui::__run_test_ui(|ui| {
/// if ui.link("Documentation").clicked() {
/// // …
/// }
/// # });
/// ```
///
/// See also [`Link`].
#[must_use = "You should check if the user clicked this with `if ui.link(…).clicked() { … } "]
pub fn link(&mut self, text: impl Into<WidgetText>) -> Response {
Link::new(text).ui(self)
}
/// Link to a web page.
///
/// Shortcut for `add(Hyperlink::new(url))`.
///
/// ```
/// # egui::__run_test_ui(|ui| {
/// ui.hyperlink("https://www.egui.rs/");
/// # });
/// ```
///
/// See also [`Hyperlink`].
pub fn hyperlink(&mut self, url: impl ToString) -> Response {
Hyperlink::new(url).ui(self)
}
/// Shortcut for `add(Hyperlink::new(url).text(label))`
/// Shortcut for `add(Hyperlink::new(url).text(label))`.
///
/// ```
/// # egui::__run_test_ui(|ui| {

94
egui/src/widgets/hyperlink.rs

@ -1,5 +1,69 @@
use crate::*;
/// Clickable text, that looks like a hyperlink.
///
/// To link to a web page, use [`Hyperlink`], [`Ui::hyperlink`] or [`Ui::hyperlink_to`].
///
/// See also [`Ui::link`].
///
/// ```
/// # egui::__run_test_ui(|ui| {
/// // These are equivalent:
/// if ui.link("Documentation").clicked() {
/// // …
/// }
///
/// if ui.add(egui::Link::new("Documentation")).clicked() {
/// // …
/// }
/// # });
/// ```
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
pub struct Link {
text: WidgetText,
}
impl Link {
pub fn new(text: impl Into<WidgetText>) -> Self {
Self { text: text.into() }
}
}
impl Widget for Link {
fn ui(self, ui: &mut Ui) -> Response {
let Link { text } = self;
let label = Label::new(text).sense(Sense::click());
let (pos, text_galley, response) = label.layout_in_ui(ui);
response.widget_info(|| WidgetInfo::labeled(WidgetType::Link, text_galley.text()));
if response.hovered() {
ui.ctx().output().cursor_icon = CursorIcon::PointingHand;
}
if ui.is_rect_visible(response.rect) {
let color = ui.visuals().hyperlink_color;
let visuals = ui.style().interact(&response);
let underline = if response.hovered() || response.has_focus() {
Stroke::new(visuals.fg_stroke.width, color)
} else {
Stroke::none()
};
ui.painter().add(epaint::TextShape {
pos,
galley: text_galley.galley,
override_text_color: Some(color),
underline,
angle: 0.0,
});
}
response
}
}
/// A clickable hyperlink, e.g. to `"https://github.com/emilk/egui"`.
///
/// See also [`Ui::hyperlink`] and [`Ui::hyperlink_to`].
@ -42,15 +106,9 @@ impl Hyperlink {
impl Widget for Hyperlink {
fn ui(self, ui: &mut Ui) -> Response {
let Hyperlink { url, text } = self;
let label = Label::new(text).sense(Sense::click());
let Self { url, text } = self;
let (pos, text_galley, response) = label.layout_in_ui(ui);
response.widget_info(|| WidgetInfo::labeled(WidgetType::Hyperlink, text_galley.text()));
if response.hovered() {
ui.ctx().output().cursor_icon = CursorIcon::PointingHand;
}
let response = ui.add(Link::new(text));
if response.clicked() {
let modifiers = ui.ctx().input().modifiers;
ui.ctx().output().open_url = Some(crate::output::OpenUrl {
@ -64,26 +122,6 @@ impl Widget for Hyperlink {
new_tab: true,
});
}
if ui.is_rect_visible(response.rect) {
let color = ui.visuals().hyperlink_color;
let visuals = ui.style().interact(&response);
let underline = if response.hovered() || response.has_focus() {
Stroke::new(visuals.fg_stroke.width, color)
} else {
Stroke::none()
};
ui.painter().add(epaint::TextShape {
pos,
galley: text_galley.galley,
override_text_color: Some(color),
underline,
angle: 0.0,
});
}
response.on_hover_text(url)
}
}

6
egui_demo_lib/src/apps/demo/widget_gallery.rs

@ -141,6 +141,12 @@ impl WidgetGallery {
}
ui.end_row();
ui.add(doc_link_label("Link", "link"));
if ui.link("Click me!").clicked() {
*boolean = !*boolean;
}
ui.end_row();
ui.add(doc_link_label("Checkbox", "checkbox"));
ui.checkbox(boolean, "Checkbox");
ui.end_row();

Loading…
Cancel
Save