mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
implement suggestion keyup/keydown keys navigation
This commit is contained in:
parent
b716fb1f78
commit
f6b34352e4
2 changed files with 89 additions and 74 deletions
|
|
@ -61,7 +61,7 @@ impl Request {
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if matches!(k, Key::Up | Key::KP_Up | Key::Page_Up | Key::KP_Page_Up) {
|
if matches!(k, Key::Up | Key::KP_Up | Key::Page_Up | Key::KP_Page_Up) {
|
||||||
if !suggestion.to_back() {
|
if !suggestion.back() {
|
||||||
entry.error_bell()
|
entry.error_bell()
|
||||||
}
|
}
|
||||||
return Propagation::Stop;
|
return Propagation::Stop;
|
||||||
|
|
@ -69,7 +69,7 @@ impl Request {
|
||||||
k,
|
k,
|
||||||
Key::Down | Key::KP_Down | Key::Page_Down | Key::KP_Page_Down
|
Key::Down | Key::KP_Down | Key::Page_Down | Key::KP_Page_Down
|
||||||
) {
|
) {
|
||||||
if !suggestion.to_next() {
|
if !suggestion.next() {
|
||||||
entry.error_bell()
|
entry.error_bell()
|
||||||
}
|
}
|
||||||
return Propagation::Stop;
|
return Propagation::Stop;
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,16 @@ use gtk::{
|
||||||
glib::SignalHandlerId,
|
glib::SignalHandlerId,
|
||||||
prelude::{EditableExt, EntryExt, ListItemExt, WidgetExt},
|
prelude::{EditableExt, EntryExt, ListItemExt, WidgetExt},
|
||||||
Entry, ListItem, ListView, Popover, SignalListItemFactory, SingleSelection,
|
Entry, ListItem, ListView, Popover, SignalListItemFactory, SingleSelection,
|
||||||
|
INVALID_LIST_POSITION,
|
||||||
};
|
};
|
||||||
pub use item::Item;
|
pub use item::Item;
|
||||||
|
use sourceview::prelude::ListModelExt;
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
pub struct Suggestion {
|
pub struct Suggestion {
|
||||||
list_store: ListStore,
|
list_store: ListStore,
|
||||||
|
list_view: ListView,
|
||||||
|
single_selection: SingleSelection,
|
||||||
request: Entry,
|
request: Entry,
|
||||||
profile: Rc<Profile>,
|
profile: Rc<Profile>,
|
||||||
popover: Popover,
|
popover: Popover,
|
||||||
|
|
@ -30,66 +34,45 @@ impl Suggestion {
|
||||||
|
|
||||||
/// Create new `Self`
|
/// Create new `Self`
|
||||||
pub fn build(profile: &Rc<Profile>, request: &Entry) -> Self {
|
pub fn build(profile: &Rc<Profile>, request: &Entry) -> Self {
|
||||||
let list_store = ListStore::new::<Item>();
|
|
||||||
let signal_handler_id = Rc::new(RefCell::new(None));
|
let signal_handler_id = Rc::new(RefCell::new(None));
|
||||||
Self {
|
let list_store = ListStore::new::<Item>();
|
||||||
profile: profile.clone(),
|
let single_selection = {
|
||||||
request: request.clone(),
|
let ss = SingleSelection::builder()
|
||||||
popover: {
|
|
||||||
let p = Popover::builder()
|
|
||||||
.autohide(false)
|
|
||||||
.can_focus(false)
|
|
||||||
.halign(gtk::Align::Start)
|
|
||||||
.child(
|
|
||||||
>k::ScrolledWindow::builder()
|
|
||||||
//.css_classes(["view"])
|
|
||||||
.child(&{
|
|
||||||
let list_view = ListView::builder()
|
|
||||||
.show_separators(true)
|
|
||||||
.model(&{
|
|
||||||
let s = SingleSelection::builder()
|
|
||||||
.model(&list_store)
|
.model(&list_store)
|
||||||
.autoselect(false)
|
.autoselect(false)
|
||||||
.build();
|
.build();
|
||||||
s.connect_selected_notify({
|
ss.connect_selected_notify({
|
||||||
let request = request.clone();
|
let request = request.clone();
|
||||||
let signal_handler_id = signal_handler_id.clone();
|
let signal_handler_id = signal_handler_id.clone();
|
||||||
move |this| {
|
move |this| {
|
||||||
if let Some(selected_item) = this.selected_item() {
|
if let Some(selected_item) = this.selected_item() {
|
||||||
use gtk::prelude::ObjectExt;
|
use gtk::prelude::ObjectExt;
|
||||||
if let Some(signal_handler_id) =
|
if let Some(signal_handler_id) = signal_handler_id.borrow().as_ref() {
|
||||||
signal_handler_id.borrow().as_ref()
|
|
||||||
{
|
|
||||||
request.block_signal(signal_handler_id);
|
request.block_signal(signal_handler_id);
|
||||||
}
|
}
|
||||||
request.set_text(
|
request.set_text(&selected_item.downcast_ref::<Item>().unwrap().request());
|
||||||
&selected_item
|
|
||||||
.downcast_ref::<Item>()
|
|
||||||
.unwrap()
|
|
||||||
.request(),
|
|
||||||
);
|
|
||||||
request.select_region(0, -1);
|
request.select_region(0, -1);
|
||||||
if let Some(signal_handler_id) =
|
if let Some(signal_handler_id) = signal_handler_id.borrow().as_ref() {
|
||||||
signal_handler_id.borrow().as_ref()
|
|
||||||
{
|
|
||||||
request.unblock_signal(signal_handler_id);
|
request.unblock_signal(signal_handler_id);
|
||||||
}
|
}
|
||||||
} // @TODO find signal to handle selected item only
|
} // @TODO find signal to handle selected item only
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
s
|
ss
|
||||||
})
|
};
|
||||||
|
let list_view = {
|
||||||
|
let lv = ListView::builder()
|
||||||
|
.show_separators(true)
|
||||||
|
.model(&single_selection)
|
||||||
.factory(&{
|
.factory(&{
|
||||||
let f = SignalListItemFactory::new();
|
let f = SignalListItemFactory::new();
|
||||||
f.connect_setup(|_, this| {
|
f.connect_setup(|_, this| {
|
||||||
this.downcast_ref::<ListItem>().unwrap().set_child(
|
this.downcast_ref::<ListItem>().unwrap().set_child(Some(
|
||||||
Some(
|
|
||||||
&ActionRow::builder()
|
&ActionRow::builder()
|
||||||
.use_markup(true)
|
.use_markup(true)
|
||||||
.use_underline(true)
|
.use_underline(true)
|
||||||
.build(),
|
.build(),
|
||||||
),
|
))
|
||||||
)
|
|
||||||
});
|
});
|
||||||
f.connect_bind(|_, this| {
|
f.connect_bind(|_, this| {
|
||||||
let l = this.downcast_ref::<ListItem>().unwrap();
|
let l = this.downcast_ref::<ListItem>().unwrap();
|
||||||
|
|
@ -101,12 +84,24 @@ impl Suggestion {
|
||||||
f
|
f
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
list_view.connect_activate({
|
lv.connect_activate({
|
||||||
let request = request.clone();
|
let request = request.clone();
|
||||||
move |_, _| request.emit_activate()
|
move |_, _| request.emit_activate()
|
||||||
});
|
});
|
||||||
list_view
|
lv
|
||||||
})
|
};
|
||||||
|
Self {
|
||||||
|
profile: profile.clone(),
|
||||||
|
request: request.clone(),
|
||||||
|
popover: {
|
||||||
|
let p = Popover::builder()
|
||||||
|
.autohide(false)
|
||||||
|
.can_focus(false)
|
||||||
|
.halign(gtk::Align::Start)
|
||||||
|
.child(
|
||||||
|
>k::ScrolledWindow::builder()
|
||||||
|
//.css_classes(["view"])
|
||||||
|
.child(&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)
|
||||||
|
|
@ -130,7 +125,9 @@ impl Suggestion {
|
||||||
p
|
p
|
||||||
},
|
},
|
||||||
signal_handler_id,
|
signal_handler_id,
|
||||||
|
single_selection,
|
||||||
list_store,
|
list_store,
|
||||||
|
list_view,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,11 +167,20 @@ impl Suggestion {
|
||||||
self.popover.popdown()
|
self.popover.popdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_back(&self) -> bool {
|
pub fn back(&self) -> bool {
|
||||||
false // @TODO
|
let position = self.single_selection.selected();
|
||||||
|
if position == 0 {
|
||||||
|
return false; // prevent unsigned value decrement
|
||||||
}
|
}
|
||||||
pub fn to_next(&self) -> bool {
|
self.select(position - 1)
|
||||||
false // @TODO
|
}
|
||||||
|
|
||||||
|
pub fn next(&self) -> bool {
|
||||||
|
let position = self.single_selection.selected();
|
||||||
|
if position == INVALID_LIST_POSITION {
|
||||||
|
return self.select(0);
|
||||||
|
}
|
||||||
|
self.select(position + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
|
|
@ -183,7 +189,16 @@ impl Suggestion {
|
||||||
self.popover.is_visible()
|
self.popover.is_visible()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*pub fn total(&self) -> u32 {
|
// Tools
|
||||||
self.list_store.n_items()
|
|
||||||
}*/
|
fn select(&self, position: u32) -> bool {
|
||||||
|
let total = self.list_store.n_items();
|
||||||
|
if position == INVALID_LIST_POSITION || position >= total || total == 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self.single_selection.set_selected(position);
|
||||||
|
self.list_view
|
||||||
|
.scroll_to(position, gtk::ListScrollFlags::NONE, None);
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue