use shared reference container for links table passed to event actions; use single hovered tag holder instead of iter entire the hashmap

This commit is contained in:
yggverse 2024-12-04 09:10:38 +02:00
parent 9d8f2498e8
commit ee2ef92831

View File

@ -26,7 +26,7 @@ use gtk::{
EventControllerMotion, GestureClick, TextBuffer, TextTag, TextWindowType, UriLauncher, Window, EventControllerMotion, GestureClick, TextBuffer, TextTag, TextWindowType, UriLauncher, Window,
WrapMode, WrapMode,
}; };
use std::{collections::HashMap, rc::Rc}; use std::{cell::Cell, collections::HashMap, rc::Rc};
pub const DATE_FORMAT: &str = "%Y-%m-%d"; pub const DATE_FORMAT: &str = "%Y-%m-%d";
pub const EXTERNAL_LINK_INDICATOR: &str = ""; pub const EXTERNAL_LINK_INDICATOR: &str = "";
@ -52,9 +52,13 @@ impl Reader {
// Init default values // Init default values
let mut title = None; let mut title = None;
// Init HashMap storage for event controllers // Init HashMap storage (for event controllers)
let mut links: HashMap<TextTag, Uri> = HashMap::new(); let mut links: HashMap<TextTag, Uri> = HashMap::new();
// Init hovered tag storage for `links`
// * maybe less expensive than update entire HashMap by iter
let hover: Rc<Cell<Option<TextTag>>> = Rc::new(Cell::new(None));
// Init multiline code builder features // Init multiline code builder features
let mut multiline = None; let mut multiline = None;
@ -305,10 +309,13 @@ impl Reader {
motion_controller.clone(), motion_controller.clone(),
)); ));
// Init shared reference container for HashTable constructed
let links = Rc::new(links);
// Init events // Init events
primary_button_controller.connect_released({ primary_button_controller.connect_released({
let text_view = widget.text_view.clone(); let text_view = widget.text_view.clone();
let _links_ = links.clone(); // is copy let links = links.clone();
move |_, _, window_x, window_y| { move |_, _, window_x, window_y| {
// Detect tag match current coords hovered // Detect tag match current coords hovered
let (buffer_x, buffer_y) = text_view.window_to_buffer_coords( let (buffer_x, buffer_y) = text_view.window_to_buffer_coords(
@ -320,7 +327,7 @@ impl Reader {
if let Some(iter) = text_view.iter_at_location(buffer_x, buffer_y) { if let Some(iter) = text_view.iter_at_location(buffer_x, buffer_y) {
for tag in iter.tags() { for tag in iter.tags() {
// Tag is link // Tag is link
if let Some(uri) = _links_.get(&tag) { if let Some(uri) = links.get(&tag) {
// Select link handler by scheme // Select link handler by scheme
return match uri.scheme().as_str() { return match uri.scheme().as_str() {
"gemini" => { "gemini" => {
@ -346,7 +353,7 @@ impl Reader {
middle_button_controller.connect_pressed({ middle_button_controller.connect_pressed({
let text_view = widget.text_view.clone(); let text_view = widget.text_view.clone();
let _links_ = links.clone(); // is copy let links = links.clone();
move |_, _, window_x, window_y| { move |_, _, window_x, window_y| {
// Detect tag match current coords hovered // Detect tag match current coords hovered
let (buffer_x, buffer_y) = text_view.window_to_buffer_coords( let (buffer_x, buffer_y) = text_view.window_to_buffer_coords(
@ -357,7 +364,7 @@ impl Reader {
if let Some(iter) = text_view.iter_at_location(buffer_x, buffer_y) { if let Some(iter) = text_view.iter_at_location(buffer_x, buffer_y) {
for tag in iter.tags() { for tag in iter.tags() {
// Tag is link // Tag is link
if let Some(uri) = _links_.get(&tag) { if let Some(uri) = links.get(&tag) {
// Select link handler by scheme // Select link handler by scheme
return match uri.scheme().as_str() { return match uri.scheme().as_str() {
"gemini" => { "gemini" => {
@ -390,7 +397,8 @@ impl Reader {
motion_controller.connect_motion({ motion_controller.connect_motion({
let text_view = widget.text_view.clone(); let text_view = widget.text_view.clone();
let _links_ = links.clone(); // is copy let links = links.clone();
let hover = hover.clone();
move |_, window_x, window_y| { move |_, window_x, window_y| {
// Detect tag match current coords hovered // Detect tag match current coords hovered
let (buffer_x, buffer_y) = text_view.window_to_buffer_coords( let (buffer_x, buffer_y) = text_view.window_to_buffer_coords(
@ -400,7 +408,7 @@ impl Reader {
); );
// Reset link colors to default // Reset link colors to default
for (tag, _) in _links_.iter() { if let Some(tag) = hover.replace(None) {
tag.set_foreground_rgba(Some(&link_color.0)); tag.set_foreground_rgba(Some(&link_color.0));
} }
@ -408,10 +416,13 @@ impl Reader {
if let Some(iter) = text_view.iter_at_location(buffer_x, buffer_y) { if let Some(iter) = text_view.iter_at_location(buffer_x, buffer_y) {
for tag in iter.tags() { for tag in iter.tags() {
// Tag is link // Tag is link
if let Some(uri) = _links_.get(&tag) { if let Some(uri) = links.get(&tag) {
// Toggle color // Toggle color
tag.set_foreground_rgba(Some(&link_color.1)); tag.set_foreground_rgba(Some(&link_color.1));
// Keep hovered tag in memory
hover.replace(Some(tag.clone()));
// Toggle cursor // Toggle cursor
text_view.set_cursor_from_name(Some("pointer")); text_view.set_cursor_from_name(Some("pointer"));