Improve viewer controls and navigation
This commit is contained in:
parent
b139395067
commit
ffa8bc93ba
2 changed files with 477 additions and 16 deletions
|
|
@ -248,6 +248,44 @@ impl BrowserController {
|
|||
let controller = Rc::clone(self);
|
||||
self.location_dropdown
|
||||
.connect_selected_notify(move |_| controller.select_profile());
|
||||
let location_factory = gtk::SignalListItemFactory::new();
|
||||
let controller = Rc::downgrade(self);
|
||||
location_factory.connect_setup(move |_, item| {
|
||||
let Some(item) = item.downcast_ref::<gtk::ListItem>() else {
|
||||
return;
|
||||
};
|
||||
let label = gtk::Label::builder().xalign(0.0).build();
|
||||
let click = gtk::GestureClick::builder().button(1).build();
|
||||
item.set_child(Some(&label));
|
||||
let item = item.downgrade();
|
||||
let controller = controller.clone();
|
||||
click.connect_released(move |_, _, _, _| {
|
||||
let Some(item) = item.upgrade() else {
|
||||
return;
|
||||
};
|
||||
let Some(controller) = controller.upgrade() else {
|
||||
return;
|
||||
};
|
||||
if is_favorites_selection(item.position(), controller.profiles().len()) {
|
||||
controller.show_favorites();
|
||||
}
|
||||
});
|
||||
label.add_controller(click);
|
||||
});
|
||||
location_factory.connect_bind(|_, item| {
|
||||
let Some(item) = item.downcast_ref::<gtk::ListItem>() else {
|
||||
return;
|
||||
};
|
||||
let Some(label) = item.child().and_downcast::<gtk::Label>() else {
|
||||
return;
|
||||
};
|
||||
let Some(value) = item.item().and_downcast::<gtk::StringObject>() else {
|
||||
return;
|
||||
};
|
||||
label.set_text(value.string().as_str());
|
||||
});
|
||||
self.location_dropdown
|
||||
.set_list_factory(Some(&location_factory));
|
||||
let controller = Rc::clone(self);
|
||||
self.search_entry
|
||||
.connect_search_changed(move |_| controller.render());
|
||||
|
|
@ -274,8 +312,14 @@ impl BrowserController {
|
|||
|
||||
let key_controller = gtk::EventControllerKey::new();
|
||||
let controller = Rc::clone(self);
|
||||
key_controller
|
||||
.connect_key_pressed(move |_, key, _, modifiers| controller.typeahead(key, modifiers));
|
||||
key_controller.connect_key_pressed(move |_, key, _, modifiers| {
|
||||
if key == gtk::gdk::Key::BackSpace {
|
||||
controller.go_up();
|
||||
glib::Propagation::Stop
|
||||
} else {
|
||||
controller.typeahead(key, modifiers)
|
||||
}
|
||||
});
|
||||
self.list_box.add_controller(key_controller);
|
||||
|
||||
let controller = Rc::clone(self);
|
||||
|
|
@ -315,7 +359,7 @@ impl BrowserController {
|
|||
fn select_profile(self: &Rc<Self>) {
|
||||
let profile_index = self.location_dropdown.selected() as usize;
|
||||
let profiles = self.profiles();
|
||||
if profile_index == profiles.len() {
|
||||
if is_favorites_selection(self.location_dropdown.selected(), profiles.len()) {
|
||||
self.show_favorites();
|
||||
return;
|
||||
}
|
||||
|
|
@ -348,7 +392,6 @@ impl BrowserController {
|
|||
self.delete_location_button.set_sensitive(false);
|
||||
self.path_entry.set_text("즐겨찾기");
|
||||
self.path_entry.set_editable(false);
|
||||
self.search_entry.set_text("");
|
||||
let entries = self
|
||||
.config
|
||||
.borrow()
|
||||
|
|
@ -357,10 +400,14 @@ impl BrowserController {
|
|||
.map(favorite_browser_entry)
|
||||
.collect();
|
||||
let mut state = self.state.borrow_mut();
|
||||
state.generation = state.generation.wrapping_add(1);
|
||||
state.typeahead_query.clear();
|
||||
state.typeahead_last_input = None;
|
||||
state.browsing_favorites = true;
|
||||
state.favorite_profile = None;
|
||||
state.entries = entries;
|
||||
drop(state);
|
||||
self.search_entry.set_text("");
|
||||
self.render();
|
||||
}
|
||||
|
||||
|
|
@ -500,7 +547,10 @@ impl BrowserController {
|
|||
let Some(controller) = controller.upgrade() else {
|
||||
return;
|
||||
};
|
||||
if controller.state.borrow().generation != generation {
|
||||
let state = controller.state.borrow();
|
||||
let stale = state.generation != generation || state.browsing_favorites;
|
||||
drop(state);
|
||||
if stale {
|
||||
return;
|
||||
}
|
||||
match result {
|
||||
|
|
@ -815,6 +865,7 @@ impl BrowserController {
|
|||
favorite_control,
|
||||
download_control,
|
||||
reuse_window,
|
||||
view_mode_control: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -846,6 +897,7 @@ impl BrowserController {
|
|||
let navigator = self.sibling_navigator(&entry, siblings, profile.clone());
|
||||
let favorite_control = self.favorite_control(&entry, &profile);
|
||||
let download_control = self.download_control(&entry);
|
||||
let view_mode_control = (kind == EntryKind::Image).then(|| self.view_mode_control());
|
||||
self.zip_cache.prepare_media(
|
||||
entry,
|
||||
move |current, total| {
|
||||
|
|
@ -868,6 +920,7 @@ impl BrowserController {
|
|||
favorite_control,
|
||||
download_control,
|
||||
reuse_window,
|
||||
view_mode_control,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -1166,7 +1219,7 @@ impl BrowserController {
|
|||
.transient_for(&self.window)
|
||||
.modal(true)
|
||||
.resizable(false)
|
||||
.default_width(360)
|
||||
.default_width(520)
|
||||
.build();
|
||||
let content = gtk::Box::new(gtk::Orientation::Vertical, 14);
|
||||
content.set_margin_top(24);
|
||||
|
|
@ -1179,12 +1232,21 @@ impl BrowserController {
|
|||
)));
|
||||
name.add_css_class("title-2");
|
||||
let contact = gtk::Label::new(Some("개발자 연락처 : burningtuna@gmail.com"));
|
||||
let libraries = gtk::Label::new(Some(
|
||||
"사용한 라이브러리\n\
|
||||
GTK4 / GIO · GStreamer · image · zip · rusqlite / SQLite\n\
|
||||
serde · toml · anyhow · chrono · filetime · percent-encoding\n\
|
||||
sha2 · tempfile",
|
||||
));
|
||||
libraries.set_xalign(0.0);
|
||||
libraries.set_wrap(true);
|
||||
let close_button = gtk::Button::with_label("닫기");
|
||||
close_button.set_halign(gtk::Align::End);
|
||||
let dialog_to_close = dialog.clone();
|
||||
close_button.connect_clicked(move |_| dialog_to_close.close());
|
||||
content.append(&name);
|
||||
content.append(&contact);
|
||||
content.append(&libraries);
|
||||
content.append(&close_button);
|
||||
dialog.set_child(Some(&content));
|
||||
dialog.present();
|
||||
|
|
@ -1449,6 +1511,10 @@ fn navigable_sibling(current: EntryKind, candidate: EntryKind) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_favorites_selection(selected: u32, profile_count: usize) -> bool {
|
||||
selected != gtk::INVALID_LIST_POSITION && selected as usize == profile_count
|
||||
}
|
||||
|
||||
fn sorted_navigable_entries(
|
||||
entries: &[BrowserEntry],
|
||||
current_kind: EntryKind,
|
||||
|
|
@ -1634,6 +1700,9 @@ mod tests {
|
|||
|
||||
assert_eq!(folder.kind, EntryKind::Directory);
|
||||
assert_eq!(archive.kind, EntryKind::ZipArchive);
|
||||
assert!(is_favorites_selection(3, 3));
|
||||
assert!(!is_favorites_selection(2, 3));
|
||||
assert!(!is_favorites_selection(gtk::INVALID_LIST_POSITION, 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue