use adw::subclass::prelude::ObjectSubclassIsExt;
use gettextrs::pgettext;
use glib::{
object::{CastNone, ObjectExt},
variant::ToVariant,
};
use gtk::{
glib,
prelude::{TextViewExt, WidgetExt},
};
use crate::{
consts::{ACTION_FIND_IN_TEXT_OPEN, ACTION_FIND_IN_TEXT_TOGGLE},
widget,
};
mod imp;
glib::wrapper! {
pub struct TextSearchBar(ObjectSubclass<imp::TextSearchBarImp>)
@extends gtk::Box, gtk::Widget,
@implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Orientable;
}
impl TextSearchBar {
pub fn new(text_view: >k::TextView) -> TextSearchBar {
let obj: TextSearchBar = glib::Object::new();
obj.imp().set_text_view(text_view);
obj
}
pub fn grab_focus_on_search_entry(&self) {
widget::grab_focus_on_search_entry(&self.imp().search_entry);
}
pub fn clear_tags(&self) {
self.imp().clear_tags();
}
pub fn find_text(&self) {
self.imp().new_find_in_text();
}
pub fn new_added_text(
&self,
buff: >k::TextBuffer,
start_iter: gtk::TextIter,
end_iter: gtk::TextIter,
) {
self.imp().new_added_text(buff, start_iter, end_iter);
}
}
pub fn create_menu_item(id: PanelID) -> (gio::MenuItem, gio::MenuItem) {
let menu_label = pgettext("text_find", "Toggle Find in Text");
let mi_toggle = gio::MenuItem::new(Some(&menu_label), None);
mi_toggle.set_action_and_target_value(Some(ACTION_FIND_IN_TEXT_TOGGLE), Some(&id.to_variant()));
let menu_label = pgettext("text_find", "Open Find in Text");
let mi_open = gio::MenuItem::new(Some(&menu_label), Some(ACTION_FIND_IN_TEXT_OPEN));
(mi_toggle, mi_open)
}
pub fn text_search_construct(
text_view: >k::TextView,
text_search_bar: >k::SearchBar,
find_text_button: >k::ToggleButton,
add_menu: bool,
id: PanelID,
) {
add_menu_fn(text_view, add_menu, id);
let text_search_bar_content = TextSearchBar::new(text_view);
text_search_bar.set_child(Some(&text_search_bar_content));
find_text_button
.bind_property("active", text_search_bar, "search-mode-enabled")
.bidirectional()
.build();
let tooltip_text = pgettext("text_find", "Open Find in Text");
find_text_button.set_tooltip_text(Some(&tooltip_text));
text_search_bar.connect_search_mode_enabled_notify(|search_bar| {
if let Some(text_search_bar) = search_bar.child().and_downcast_ref::<TextSearchBar>() {
if search_bar.is_search_mode() {
text_search_bar.find_text();
} else {
text_search_bar.clear_tags();
}
};
});
}
pub fn on_new_text(search_bar: >k::SearchBar) {
if !search_bar.is_search_mode() {
return;
}
if let Some(text_search_bar) = search_bar.child().and_downcast_ref::<TextSearchBar>() {
text_search_bar.find_text();
}
}
pub fn update_text_view(
text_search_bar: >k::SearchBar,
text_view: >k::TextView,
add_menu: bool,
id: PanelID,
) {
add_menu_fn(text_view, add_menu, id);
if let Some(search_bar) = text_search_bar.child().and_downcast_ref::<TextSearchBar>() {
search_bar.imp().set_text_view(text_view);
}
}
fn add_menu_fn(text_view: >k::TextView, add_menu: bool, id: PanelID) {
if !add_menu {
return;
}
let menu = gio::Menu::new();
let (toggle, open) = create_menu_item(id);
menu.append_item(&toggle);
menu.append_item(&open);
let menu_sec = gio::Menu::new();
menu_sec.append_section(None, &menu);
text_view.set_extra_menu(Some(&menu_sec));
}
pub fn new_added_text(
text_search_bar: >k::SearchBar,
buff: >k::TextBuffer,
start_iter: gtk::TextIter,
end_iter: gtk::TextIter,
) {
if let Some(search_bar) = text_search_bar.child().and_downcast_ref::<TextSearchBar>() {
search_bar.imp().new_added_text(buff, start_iter, end_iter);
}
}
pub enum PanelID {
Info,
Dependencies,
File,
Journal,
}
impl PanelID {
fn to_variant(&self) -> glib::Variant {
match self {
PanelID::Info => 1.to_variant(),
PanelID::Dependencies => 2.to_variant(),
PanelID::File => 3.to_variant(),
PanelID::Journal => 4.to_variant(),
}
}
}
impl From<Option<&glib::Variant>> for PanelID {
fn from(value: Option<&glib::Variant>) -> Self {
if let Some(variant) = value
&& let Some(val) = variant.get::<i32>()
{
match val {
1 => PanelID::Info,
2 => PanelID::Dependencies,
3 => PanelID::File,
4 => PanelID::Journal,
_ => PanelID::Info,
}
} else {
Self::Info
}
}
}
pub fn focus_on_text_entry(text_search_bar: >k::SearchBar) {
if let Some(search) = text_search_bar.child().and_downcast_ref::<TextSearchBar>() {
search.grab_focus_on_search_entry();
}
}