export entire TextView widget reference to the Search component

This commit is contained in:
yggverse 2024-12-17 02:13:47 +02:00
parent e0cb5d7a0f
commit 8b65df99f4
8 changed files with 52 additions and 43 deletions

View File

@ -575,7 +575,7 @@ impl Page {
};
// Update `find` model with new buffer
search.update(Some(text_widget.buffer));
search.update(Some(text_widget.text_view));
// Update page meta
meta.set_status(Status::Success)

View File

@ -7,8 +7,8 @@ use source::Source;
use super::{BrowserAction, TabAction, WindowAction};
use gtk::{
glib::Uri,
prelude::{BoxExt, TextViewExt},
Box, Orientation, ScrolledWindow, TextBuffer,
prelude::{BoxExt, Cast},
Box, Orientation, ScrolledWindow, TextView,
};
use std::rc::Rc;
@ -17,7 +17,7 @@ pub struct Meta {
} // @TODO move to separated mod
pub struct Text {
pub buffer: TextBuffer,
pub text_view: TextView,
pub g_box: Box,
pub meta: Meta,
}
@ -91,7 +91,7 @@ impl Text {
});*/
Self {
buffer: gemini.reader.widget.text_view.buffer(),
text_view: gemini.reader.widget.text_view.clone().upcast::<TextView>(),
meta: Meta {
title: gemini.reader.title.clone(),
},
@ -108,7 +108,7 @@ impl Text {
g_box.append(&ScrolledWindow::builder().child(&source.text_view).build());
Self {
buffer: source.text_view.buffer(),
text_view: source.text_view.upcast::<TextView>(),
meta: Meta { title: None },
g_box,
}

View File

@ -1,19 +1,19 @@
mod buffer;
mod form;
mod placeholder;
mod subject;
use buffer::Buffer;
use form::Form;
use placeholder::Placeholder;
use subject::Subject;
use gtk::{
prelude::{BoxExt, WidgetExt},
Align, Box, Orientation, TextBuffer,
Align, Box, Orientation, TextBuffer, TextView,
};
use std::{cell::RefCell, rc::Rc};
pub struct Search {
buffer: Rc<RefCell<Option<Buffer>>>,
subject: Rc<RefCell<Option<Subject>>>,
pub form: Rc<Form>,
pub placeholder: Rc<Placeholder>,
pub g_box: Box,
@ -25,8 +25,8 @@ impl Search {
/// Create new `Self`
pub fn new() -> Self {
// Init components
let buffer = Rc::new(RefCell::new(None));
let form = Rc::new(Form::new(&buffer));
let subject = Rc::new(RefCell::new(None));
let form = Rc::new(Form::new(&subject));
let placeholder = Rc::new(Placeholder::new());
// Init main container
@ -42,7 +42,7 @@ impl Search {
// Done
Self {
buffer,
subject,
form,
g_box,
placeholder,
@ -52,7 +52,7 @@ impl Search {
// Actions
pub fn show(&self) {
if self.buffer.borrow().is_some() {
if self.subject.borrow().is_some() {
self.form.show();
self.placeholder.hide();
} else {
@ -74,9 +74,10 @@ impl Search {
}
}
pub fn update(&self, text_buffer: Option<TextBuffer>) {
self.buffer.replace(match text_buffer {
Some(buffer) => Some(Buffer::new(buffer)),
/// * currently supports [TextView](https://docs.gtk.org/gtk4/class.TextView.html) only
pub fn update(&self, text_view: Option<TextView>) {
self.subject.replace(match text_view {
Some(subject) => Some(Subject::new(subject)),
None => None,
});
}

View File

@ -3,12 +3,14 @@ mod input;
mod match_case;
mod navigation;
use super::Buffer;
use super::Subject;
use input::Input;
use navigation::Navigation;
use gtk::{
prelude::{BoxExt, ButtonExt, CheckButtonExt, EditableExt, TextBufferExt, WidgetExt},
prelude::{
BoxExt, ButtonExt, CheckButtonExt, EditableExt, TextBufferExt, TextViewExt, WidgetExt,
},
Align, Box, Orientation, TextIter, TextSearchFlags,
};
use std::{cell::RefCell, rc::Rc};
@ -21,7 +23,7 @@ impl Form {
// Constructors
/// Create new `Self`
pub fn new(buffer: &Rc<RefCell<Option<Buffer>>>) -> Self {
pub fn new(buffer: &Rc<RefCell<Option<Subject>>>) -> Self {
// Init components
let close = close::new();
let input = Rc::new(Input::new());
@ -99,41 +101,44 @@ impl Form {
// Tools
fn find(
buffer: &Rc<RefCell<Option<Buffer>>>,
subject: &str,
subject: &Rc<RefCell<Option<Subject>>>,
request: &str,
is_match_case: bool,
) -> Vec<(TextIter, TextIter)> {
// Init matches holder
let mut result = Vec::new();
// Borrow buffer
match buffer.borrow().as_ref() {
Some(buffer) => {
match subject.borrow().as_ref() {
Some(subject) => {
// Get iters
let buffer_start = buffer.text_buffer.start_iter();
let buffer_end = buffer.text_buffer.end_iter();
let buffer_start = subject.text_view.buffer().start_iter();
let buffer_end = subject.text_view.buffer().end_iter();
// Cleanup previous search highlights
buffer
.text_buffer
.remove_tag(&buffer.tag.current, &buffer_start, &buffer_end);
buffer
.text_buffer
.remove_tag(&buffer.tag.found, &buffer_start, &buffer_end);
subject
.text_view
.buffer()
.remove_tag(&subject.tag.current, &buffer_start, &buffer_end);
subject
.text_view
.buffer()
.remove_tag(&subject.tag.found, &buffer_start, &buffer_end);
// Begin new search
let mut next = buffer_start;
while let Some((match_start, match_end)) = next.forward_search(
subject,
request,
match is_match_case {
true => TextSearchFlags::TEXT_ONLY,
false => TextSearchFlags::CASE_INSENSITIVE,
},
None, // unlimited
) {
buffer
.text_buffer
.apply_tag(&buffer.tag.found, &match_start, &match_end);
subject
.text_view
.buffer()
.apply_tag(&subject.tag.found, &match_start, &match_end);
next = match_end;
result.push((match_start, match_end));
}

View File

@ -2,24 +2,27 @@ mod tag;
use tag::Tag;
use gtk::{prelude::TextBufferExt, TextBuffer};
use gtk::{
prelude::{TextBufferExt, TextViewExt},
TextView,
};
pub struct Buffer {
pub text_buffer: TextBuffer,
pub struct Subject {
pub text_view: TextView,
pub tag: Tag,
}
impl Buffer {
impl Subject {
// Constructors
/// Create new `Self`
pub fn new(text_buffer: TextBuffer) -> Self {
pub fn new(text_view: TextView) -> Self {
// Init components
// * create new tag objects required for new buffer,
// instead of re-use existing refs (maybe the bug)
let tag = Tag::new(text_buffer.tag_table());
let tag = Tag::new(text_view.buffer().tag_table());
// Init `Self`
Self { text_buffer, tag }
Self { text_view, tag }
}
}