mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-04-02 09:35:28 +00:00
implement autocomplete selection event
This commit is contained in:
parent
5b0de227c0
commit
907dcd4893
2 changed files with 79 additions and 27 deletions
|
|
@ -82,7 +82,7 @@ impl Request for Entry {
|
||||||
entry.update_primary_icon(profile);
|
entry.update_primary_icon(profile);
|
||||||
|
|
||||||
// Init additional features
|
// Init additional features
|
||||||
let suggestion = Suggestion::build(&entry);
|
let suggestion = Rc::new(Suggestion::build(profile, &entry));
|
||||||
|
|
||||||
// Connect events
|
// Connect events
|
||||||
entry.connect_icon_release({
|
entry.connect_icon_release({
|
||||||
|
|
@ -102,7 +102,11 @@ impl Request for Entry {
|
||||||
|
|
||||||
entry.connect_has_focus_notify(|this| this.update_secondary_icon());
|
entry.connect_has_focus_notify(|this| this.update_secondary_icon());
|
||||||
|
|
||||||
entry.connect_changed({
|
suggestion
|
||||||
|
.clone()
|
||||||
|
.signal_handler_id
|
||||||
|
.borrow_mut()
|
||||||
|
.replace(entry.connect_changed({
|
||||||
let profile = profile.clone();
|
let profile = profile.clone();
|
||||||
let item_action = item_action.clone();
|
let item_action = item_action.clone();
|
||||||
move |this| {
|
move |this| {
|
||||||
|
|
@ -116,10 +120,10 @@ impl Request for Entry {
|
||||||
|
|
||||||
// Show search suggestions
|
// Show search suggestions
|
||||||
if this.focus_child().is_some() {
|
if this.focus_child().is_some() {
|
||||||
suggestion.update(&profile, this, None);
|
suggestion.update(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})); // `suggestion` wants `signal_handler_id` to block this event on autocomplete navigation
|
||||||
|
|
||||||
entry.connect_activate({
|
entry.connect_activate({
|
||||||
let item_action = item_action.clone();
|
let item_action = item_action.clone();
|
||||||
|
|
@ -142,7 +146,7 @@ impl Request for Entry {
|
||||||
&& state.contains(StateFlags::ACTIVE | StateFlags::FOCUS_WITHIN)
|
&& state.contains(StateFlags::ACTIVE | StateFlags::FOCUS_WITHIN)
|
||||||
&& this.selection_bounds().is_none()
|
&& this.selection_bounds().is_none()
|
||||||
{
|
{
|
||||||
this.select_region(0, this.text_length().into());
|
this.select_region(0, -1);
|
||||||
}
|
}
|
||||||
// Update last focus state
|
// Update last focus state
|
||||||
has_focus.replace(state.contains(StateFlags::FOCUS_WITHIN));
|
has_focus.replace(state.contains(StateFlags::FOCUS_WITHIN));
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
mod item;
|
mod item;
|
||||||
|
|
||||||
|
use super::Profile;
|
||||||
use adw::{
|
use adw::{
|
||||||
prelude::{ActionRowExt, PopoverExt, PreferencesRowExt},
|
prelude::{ActionRowExt, PopoverExt, PreferencesRowExt},
|
||||||
ActionRow,
|
ActionRow,
|
||||||
|
|
@ -9,13 +10,19 @@ use gtk::{
|
||||||
prelude::{Cast, CastNone},
|
prelude::{Cast, CastNone},
|
||||||
ListStore,
|
ListStore,
|
||||||
},
|
},
|
||||||
prelude::{EntryExt, ListItemExt, WidgetExt},
|
glib::SignalHandlerId,
|
||||||
|
prelude::{EditableExt, EntryExt, ListItemExt, WidgetExt},
|
||||||
Entry, ListItem, ListView, Popover, SignalListItemFactory, SingleSelection,
|
Entry, ListItem, ListView, Popover, SignalListItemFactory, SingleSelection,
|
||||||
};
|
};
|
||||||
pub use item::Item;
|
pub use item::Item;
|
||||||
|
use sourceview::prelude::ListModelExt;
|
||||||
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
pub struct Suggestion {
|
pub struct Suggestion {
|
||||||
list_store: ListStore,
|
list_store: ListStore,
|
||||||
|
request: Entry,
|
||||||
|
profile: Rc<Profile>,
|
||||||
|
pub signal_handler_id: Rc<RefCell<Option<SignalHandlerId>>>,
|
||||||
pub popover: Popover,
|
pub popover: Popover,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -23,9 +30,12 @@ impl Suggestion {
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn build(request: &Entry) -> Self {
|
pub fn build(profile: &Rc<Profile>, request: &Entry) -> Self {
|
||||||
let list_store = ListStore::new::<Item>();
|
let list_store = ListStore::new::<Item>();
|
||||||
|
let signal_handler_id = Rc::new(RefCell::new(None));
|
||||||
Self {
|
Self {
|
||||||
|
profile: profile.clone(),
|
||||||
|
request: request.clone(),
|
||||||
popover: {
|
popover: {
|
||||||
let p = Popover::builder()
|
let p = Popover::builder()
|
||||||
.autohide(false)
|
.autohide(false)
|
||||||
|
|
@ -34,8 +44,10 @@ impl Suggestion {
|
||||||
.child(
|
.child(
|
||||||
>k::ScrolledWindow::builder()
|
>k::ScrolledWindow::builder()
|
||||||
//.css_classes(["view"])
|
//.css_classes(["view"])
|
||||||
.child(
|
.child(&{
|
||||||
&ListView::builder()
|
let list_view = ListView::builder()
|
||||||
|
.show_separators(true)
|
||||||
|
.single_click_activate(true)
|
||||||
.model(
|
.model(
|
||||||
&SingleSelection::builder()
|
&SingleSelection::builder()
|
||||||
.model(&list_store)
|
.model(&list_store)
|
||||||
|
|
@ -63,8 +75,37 @@ impl Suggestion {
|
||||||
});
|
});
|
||||||
f
|
f
|
||||||
})
|
})
|
||||||
.build(),
|
.build();
|
||||||
)
|
list_view.connect_activate({
|
||||||
|
let request = request.clone();
|
||||||
|
let signal_handler_id = signal_handler_id.clone();
|
||||||
|
move |this, i| {
|
||||||
|
use gtk::prelude::ObjectExt;
|
||||||
|
if let Some(signal_handler_id) =
|
||||||
|
signal_handler_id.borrow().as_ref()
|
||||||
|
{
|
||||||
|
request.block_signal(signal_handler_id);
|
||||||
|
}
|
||||||
|
request.set_text(
|
||||||
|
&this
|
||||||
|
.model()
|
||||||
|
.unwrap()
|
||||||
|
.item(i)
|
||||||
|
.unwrap()
|
||||||
|
.downcast_ref::<Item>()
|
||||||
|
.unwrap()
|
||||||
|
.request(),
|
||||||
|
);
|
||||||
|
request.select_region(0, -1);
|
||||||
|
if let Some(signal_handler_id) =
|
||||||
|
signal_handler_id.borrow().as_ref()
|
||||||
|
{
|
||||||
|
request.unblock_signal(signal_handler_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
list_view
|
||||||
|
})
|
||||||
.max_content_height(400)
|
.max_content_height(400)
|
||||||
.hscrollbar_policy(gtk::PolicyType::Never)
|
.hscrollbar_policy(gtk::PolicyType::Never)
|
||||||
.propagate_natural_height(true)
|
.propagate_natural_height(true)
|
||||||
|
|
@ -87,17 +128,18 @@ impl Suggestion {
|
||||||
});
|
});
|
||||||
p
|
p
|
||||||
},
|
},
|
||||||
|
signal_handler_id,
|
||||||
list_store,
|
list_store,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self, profile: &super::Profile, request: &Entry, limit: Option<usize>) {
|
pub fn update(&self, limit: Option<usize>) {
|
||||||
use gtk::prelude::EditableExt;
|
use gtk::prelude::EditableExt;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
if request.text_length() > 0 {
|
if self.request.text_length() > 0 {
|
||||||
self.list_store.remove_all();
|
self.list_store.remove_all();
|
||||||
let query = request.text();
|
let query = self.request.text();
|
||||||
let items = profile.bookmark.contains_request(&query, limit);
|
let items = self.profile.bookmark.contains_request(&query, limit);
|
||||||
if !items.is_empty() {
|
if !items.is_empty() {
|
||||||
for item in items
|
for item in items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
@ -109,6 +151,12 @@ impl Suggestion {
|
||||||
item.request.clone(),
|
item.request.clone(),
|
||||||
)); // @TODO
|
)); // @TODO
|
||||||
}
|
}
|
||||||
|
self.popover
|
||||||
|
.child()
|
||||||
|
.unwrap()
|
||||||
|
.downcast_ref::<gtk::ScrolledWindow>()
|
||||||
|
.unwrap()
|
||||||
|
.set_height_request(-1);
|
||||||
self.popover.popup();
|
self.popover.popup();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue