Commit 58a0197a authored by Bilal Elmoussaoui's avatar Bilal Elmoussaoui
Browse files

Search: display only contexts with results & add no-results view

Also rewrote the code to better handle some internals
Still learning rust :P
parent 4a0ceb6f
Pipeline #97263 passed with stages
in 6 minutes and 35 seconds
.icons-view-title {
font-size: 16px;
font-weight: bold;
padding: 6px;
}
.no-results-label {
font-size: 32px;
font-weight: bold;
padding: 32px;
}
......@@ -14,7 +14,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="show_close_button">True</property>
<property name="centering_policy">1</property>
<property name="centering_policy">HDY_CENTERING_POLICY_STRICT</property>
<child type="title">
<object class="HdyColumn">
<property name="visible">True</property>
......
use crate::widgets::export::ExportDialog;
use glib::Cast;
use gtk;
use gtk::prelude::{BoxExt, ContainerExt, FlowBoxExt, GtkWindowExt, IconThemeExt, StyleContextExt, WidgetExt};
struct IconView {
pub widget: gtk::Box,
icon_name: String,
}
impl IconView {
pub fn new(icon_name: String) -> IconView {
let container = gtk::Box::new(gtk::Orientation::Vertical, 6);
container.set_name(icon_name.as_str());
let icon_img = gtk::Image::new_from_icon_name(Some(icon_name.as_str()), gtk::IconSize::Dnd);
container.pack_start(&icon_img, false, false, 0);
IconView {
widget: container,
icon_name: icon_name,
}
}
}
use gtk::prelude::{BoxExt, ContainerExt, FlowBoxExt, GtkWindowExt, IconThemeExt, ImageExt, StackExt, StyleContextExt, WidgetExt};
use libhandy::{Column, ColumnExt};
use std::cell::RefCell;
pub struct IconsView {
pub widget: gtk::Box,
pub widget: gtk::Stack,
icons_container: gtk::Box,
icons_contexts: Vec<RefCell<IconsViewContext>>,
}
impl IconsView {
pub fn new(parent: &gtk::ApplicationWindow) -> IconsView {
let widget = gtk::Box::new(gtk::Orientation::Vertical, 0);
let widget = gtk::Stack::new();
let icons_container = gtk::Box::new(gtk::Orientation::Vertical, 6);
icons_container.set_valign(gtk::Align::Start);
let icons_view = IconsView { widget };
let icons_contexts: Vec<RefCell<IconsViewContext>> = Vec::new();
let mut icons_view = IconsView {
widget,
icons_container,
icons_contexts,
};
icons_view.init();
icons_view.fill(&parent);
icons_view
}
fn fill(&self, parent: &gtk::ApplicationWindow) {
fn init(&self) {
// No results view
let no_results_view = gtk::Box::new(gtk::Orientation::Vertical, 6);
no_results_view.get_style_context().add_class("dim-label");
no_results_view.set_valign(gtk::Align::Center);
no_results_view.set_halign(gtk::Align::Center);
let no_results_image = gtk::Image::new_from_icon_name("system-search-symbolic", gtk::IconSize::Dialog);
no_results_image.set_pixel_size(96);
let no_results_label = gtk::Label::new(Some("No results found"));
no_results_label.get_style_context().add_class("no-results-label");
no_results_view.pack_start(&no_results_image, false, false, 0);
no_results_view.pack_start(&no_results_label, false, false, 0);
self.widget.add_named(&no_results_view, "no-results");
let column = Column::new();
column.set_maximum_width(900);
// we can't call add as libhandy::Column is not seen as a gtkContainer
// Thanks to Jordan (Podcasts) for the tip :P
let column = column.upcast::<gtk::Widget>();
let column = column.downcast::<gtk::Container>().unwrap();
column.add(&self.icons_container);
column.set_margin_bottom(24);
let scrolled_window = gtk::ScrolledWindow::new(gtk::NONE_ADJUSTMENT, gtk::NONE_ADJUSTMENT);
scrolled_window.set_vexpand(true);
scrolled_window.add(&column);
self.widget.add_named(&scrolled_window, "results");
scrolled_window.show_all();
}
fn fill(&mut self, parent: &gtk::ApplicationWindow) {
let legacy_contexts = vec!["Legacy"];
let theme = gtk::IconTheme::get_default().unwrap();
let mut icon_contexts = theme.list_contexts();
......@@ -48,23 +76,22 @@ impl IconsView {
continue;
}
let icons_view_context = IconsViewContext::new(context_str.to_string(), &parent);
self.widget.pack_start(&icons_view_context.widget, true, true, 12);
self.icons_container.pack_start(&icons_view_context.widget, true, true, 12);
self.icons_contexts.push(RefCell::new(icons_view_context));
}
}
pub fn filter(&self, search_str: String) {
let s = search_str.clone();
let filter_closure = move |flowboxchild: &gtk::FlowBoxChild| -> bool {
let row_container = &flowboxchild.get_children()[0];
let icon_name = &row_container.get_name().unwrap().as_str().to_string();
icon_name.contains(s.as_str())
};
for child in self.widget.get_children() {
let icons_view_context = child.downcast::<gtk::Container>().unwrap();
let flowbox_widget = &icons_view_context.get_children()[1];
let flowbox = flowbox_widget.clone().downcast::<gtk::FlowBox>().unwrap();
let search_str = search_str.clone();
flowbox.set_filter_func(Some(Box::new(filter_closure.clone())));
let mut total_results = 0;
for icons_context in self.icons_contexts.iter() {
icons_context.borrow_mut().filter(search_str.clone());
total_results += icons_context.borrow_mut().n_last_search_results;
}
if total_results != 0 {
self.widget.set_visible_child_name("results");
} else {
self.widget.set_visible_child_name("no-results");
}
}
}
......@@ -73,6 +100,8 @@ struct IconsViewContext {
pub widget: gtk::Box,
pub context: String,
icons_container: gtk::FlowBox,
icons: Vec<RefCell<IconView>>,
n_last_search_results: u32,
}
impl IconsViewContext {
......@@ -81,7 +110,15 @@ impl IconsViewContext {
widget.set_valign(gtk::Align::Fill);
widget.set_halign(gtk::Align::Fill);
let icons_container = gtk::FlowBox::new();
let icons_view = IconsViewContext { widget, context, icons_container };
let icons: Vec<RefCell<IconView>> = Vec::new();
let n_last_search_results: u32 = 0;
let mut icons_view = IconsViewContext {
widget,
context,
icons_container,
icons,
n_last_search_results,
};
icons_view.init();
icons_view.fill(&parent);
......@@ -96,7 +133,7 @@ impl IconsViewContext {
self.widget.add(&context_label);
}
fn fill(&self, parent: &gtk::ApplicationWindow) {
fn fill(&mut self, parent: &gtk::ApplicationWindow) {
let theme = gtk::IconTheme::get_default();
let mut icons = theme.unwrap().list_icons(Some(self.context.as_str()));
icons.sort_by(|a, b| a.as_str().cmp(&b.as_str()));
......@@ -134,8 +171,47 @@ impl IconsViewContext {
if icon_name.ends_with("-symbolic") {
let icon_view = IconView::new(icon_name);
self.icons_container.add(&icon_view.widget);
self.icons.push(RefCell::new(icon_view));
}
}
self.widget.add(&self.icons_container);
}
pub fn filter(&mut self, search_str: String) {
self.n_last_search_results = 0;
let filter_closure = move |flowboxchild: &gtk::FlowBoxChild| -> bool {
let row_container = &flowboxchild.get_children()[0];
let icon_name = &row_container.get_name().unwrap().as_str().to_string();
let searched_str = search_str.as_str();
icon_name.contains(searched_str)
};
self.icons_container.set_filter_func(Some(Box::new(filter_closure)));
for child in self.icons_container.get_children() {
if child.get_child_visible() {
self.n_last_search_results += 1;
}
}
self.widget.set_visible(self.n_last_search_results != 0);
}
}
struct IconView {
pub widget: gtk::Box,
icon_name: String,
}
impl IconView {
pub fn new(icon_name: String) -> IconView {
let container = gtk::Box::new(gtk::Orientation::Vertical, 6);
container.set_name(icon_name.as_str());
let icon_img = gtk::Image::new_from_icon_name(Some(icon_name.as_str()), gtk::IconSize::Dnd);
container.pack_start(&icon_img, false, false, 0);
IconView {
widget: container,
icon_name: icon_name,
}
}
}
......@@ -2,7 +2,6 @@ use crate::config::{APP_ID, PROFILE};
use crate::widgets::IconsView;
use crate::window_state;
use gtk::prelude::*;
use libhandy::{Column, ColumnExt};
pub struct Window {
pub widget: gtk::ApplicationWindow,
......@@ -44,20 +43,7 @@ impl Window {
});
// Init the widgets
let icons_view = IconsView::new(&self.widget);
let column = Column::new();
column.set_maximum_width(900);
// we can't call add as libhandy::Column is not seen as a gtkContainer
// Thanks to Jordan (Podcasts) for the tip :P
let column = column.upcast::<gtk::Widget>();
let column = column.downcast::<gtk::Container>().unwrap();
column.add(&icons_view.widget);
column.set_margin_bottom(24);
let scrolled_window = gtk::ScrolledWindow::new(gtk::NONE_ADJUSTMENT, gtk::NONE_ADJUSTMENT);
scrolled_window.set_vexpand(true);
scrolled_window.add(&column);
self.widget.add(&scrolled_window);
self.widget.add(&icons_view.widget);
// Search
self.search_entry.connect_changed(move |entry| {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment