[fractal] Let ScrollWidget handle scrolls
- From: Daniel Garcia Moreno <danigm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal] Let ScrollWidget handle scrolls
- Date: Mon, 9 Nov 2020 09:32:24 +0000 (UTC)
commit 2d8350ee341c806486cf028594ede5abcafb4526
Author: Kai A. Hiller <V02460 gmail com>
Date: Tue Oct 27 10:56:50 2020 +0100
Let ScrollWidget handle scrolls
fractal-gtk/src/widgets/room_history.rs | 23 ++++-----
fractal-gtk/src/widgets/scroll_widget.rs | 80 ++++++++++++++++++++++++++++----
2 files changed, 81 insertions(+), 22 deletions(-)
---
diff --git a/fractal-gtk/src/widgets/room_history.rs b/fractal-gtk/src/widgets/room_history.rs
index 2c097f0c..4b704691 100644
--- a/fractal-gtk/src/widgets/room_history.rs
+++ b/fractal-gtk/src/widgets/room_history.rs
@@ -60,16 +60,12 @@ impl List {
/// ### Panics
/// Panics if `index > len`.
pub fn add_item(&mut self, index: usize, element: Element) {
- /* Spinner is at position 0, so increment index by 1 */
- self.listbox
- .insert(element.get_listbox_row(), (index + 1) as i32);
+ self.view.insert(index, element.get_listbox_row());
self.list.insert(self.list.len() - index, element);
}
pub fn add_top(&mut self, element: Element) {
- self.view.set_balance_top();
self.add_item(0, element);
- self.view.set_kinetic_scrolling(true);
/* TODO: update the previous message:
* we need to update the previous row because it could be that we have to remove the header */
}
@@ -81,16 +77,15 @@ impl List {
self.add_item(self.list.len(), element);
}
- fn remove_item(&mut self, index: usize, row: >k::ListBoxRow) {
+ fn remove_item(&mut self, index: usize) {
self.list.remove(index);
- self.listbox.remove(row);
+ self.view.remove(self.list.len() - index - 1);
}
- fn replace_item(&mut self, index: usize, row: >k::ListBoxRow, element: Element) {
- /* Spinner is at position 0, so increment index by 1 */
- self.listbox
- .insert(element.get_listbox_row(), (self.list.len() - index) as i32);
- self.listbox.remove(row);
+ fn replace_item(&mut self, index: usize, element: Element) {
+ self.view.remove(self.list.len() - index - 1);
+ self.view
+ .insert(self.list.len() - index - 1, element.get_listbox_row());
self.list[index] = element;
}
@@ -636,7 +631,7 @@ impl RoomHistory {
self.access_token.clone(),
&self.rows,
));
- rows.replace_item(i, msg_widget.get_listbox_row(), Element::Message(item));
+ rows.replace_item(i, Element::Message(item));
None
}
@@ -661,7 +656,7 @@ impl RoomHistory {
let msg_widget = msg.widget.clone()?;
let msg_sender = msg.sender.clone();
msg.msg.redacted = true;
- rows.remove_item(i, msg_widget.get_listbox_row());
+ rows.remove_item(i);
// If the redacted message was a header message let's set
// the header on the next non-redacted message instead.
diff --git a/fractal-gtk/src/widgets/scroll_widget.rs b/fractal-gtk/src/widgets/scroll_widget.rs
index bd8a224b..a3bc33b9 100644
--- a/fractal-gtk/src/widgets/scroll_widget.rs
+++ b/fractal-gtk/src/widgets/scroll_widget.rs
@@ -10,8 +10,6 @@ use gtk::prelude::*;
use libhandy::prelude::*;
-// This really requires to opt-out of the lint
-#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq)]
enum Position {
Top,
@@ -217,14 +215,29 @@ impl ScrollWidget {
None
}
- pub fn set_balance_top(&self) {
- /* FIXME: Workaround: https://gitlab.gnome.org/GNOME/gtk/merge_requests/395 */
- self.widgets.view.set_kinetic_scrolling(false);
- self.balance.set(Some(Position::Top));
+ /// Inserts an element to the list and adjusts the scoll position.
+ ///
+ /// ### Panics
+ /// Panics if `index > number of elements`.
+ pub fn insert(&self, index: usize, row: >k::ListBoxRow) {
+ // Spinner is at position 0, so increment index by 1.
+ self.set_balance(index + 1); // might panic
+ self.widgets.listbox.insert(row, (index + 1) as i32);
+ self.widgets.view.set_kinetic_scrolling(true);
}
- pub fn set_kinetic_scrolling(&self, enabled: bool) {
- self.widgets.view.set_kinetic_scrolling(enabled);
+ /// Removes an element from the list and adjusts the scoll position.
+ ///
+ /// ### Panics
+ /// Panics if `index >= number of elements`.
+ pub fn remove(&self, index: usize) {
+ // Spinner is at position 0, so increment index by 1.
+ self.set_balance(index + 1); // might panic
+ match self.widgets.listbox.get_row_at_index((index + 1) as i32) {
+ Some(row) => self.widgets.listbox.remove(&row),
+ None => panic!("Could not remove element due to invalid index"),
+ }
+ self.widgets.view.set_kinetic_scrolling(true);
}
pub fn get_listbox(&self) -> gtk::ListBox {
@@ -251,6 +264,57 @@ impl ScrollWidget {
self.widgets.typing_label.set_markup(typing_str);
}
}
+
+ /// Sets the balance for a change happening at the given index.
+ ///
+ /// ### Panics
+ /// Panics if `index > number of listbox children`.
+ fn set_balance(&self, index: usize) {
+ /* FIXME: Workaround: https://gitlab.gnome.org/GNOME/gtk/merge_requests/395 */
+ self.widgets.view.set_kinetic_scrolling(false);
+
+ // Calculate relative positions
+ let change_pos = self.get_relative_index_pos(index); // might panic
+ let scroll_pos = self.get_relative_scroll_pos();
+
+ if change_pos < scroll_pos {
+ // Insertion happens in or above the view, so it needs adjustment.
+ self.balance.set(Some(Position::Top));
+ } else {
+ self.balance.set(Some(Position::Bottom));
+ }
+ }
+
+ /// Returns the relative position of a given index for the listbox.
+ ///
+ /// - `index == 0` will return 0.0
+ /// - `index == number of listbox children` will return 1.0
+ ///
+ /// ### Panics
+ /// Panics if `index > number of listbox children`.
+ fn get_relative_index_pos(&self, index: usize) -> f64 {
+ if index == self.widgets.listbox.get_children().len() {
+ return 1.0;
+ }
+
+ let row_at_index = self
+ .widgets
+ .listbox
+ .get_row_at_index(index as i32)
+ .expect("Index out of bounds");
+ let y = row_at_index.get_allocation().y as f64;
+ let listbox_height = self.widgets.listbox.get_allocated_height() as f64;
+
+ y / listbox_height
+ }
+
+ /// Returns the relative position of the view's bottom.
+ fn get_relative_scroll_pos(&self) -> f64 {
+ match self.widgets.view.get_vadjustment() {
+ Some(adj) => (adj.get_value() + adj.get_page_size()) / adj.get_upper(),
+ None => 1.0,
+ }
+ }
}
pub fn page_up(sw: gtk::ScrolledWindow) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]