add new tab item action group, delegate history handle to action implementation

This commit is contained in:
yggverse 2025-01-25 17:28:05 +02:00
parent 5145a53bfa
commit 913030a955
29 changed files with 409 additions and 232 deletions

View file

@ -0,0 +1,79 @@
mod back;
mod forward;
mod memory;
use back::Back;
use forward::Forward;
use gtk::{gio::SimpleAction, glib::GString};
use memory::Memory;
use std::rc::Rc;
pub struct History {
memory: Rc<Memory>,
pub back: SimpleAction,
pub forward: SimpleAction,
}
impl History {
// Constructors
/// Build new activated `Self`
pub fn build(callback: impl Fn(GString) + 'static) -> Self {
// Init childs
let memory = Rc::new(Memory::new());
let back = SimpleAction::back();
let forward = SimpleAction::forward();
// Init events
let callback = Rc::new(callback);
back.connect_activate({
let callback = callback.clone();
let forward = forward.clone();
let memory = memory.clone();
move |this, _| {
if let Some(request) = memory.back(true) {
callback(request)
}
forward.set_enabled(memory.next(false).is_some());
this.set_enabled(memory.back(false).is_some());
}
});
forward.connect_activate({
let back = back.clone();
let callback = callback.clone();
let memory = memory.clone();
move |this, _| {
if let Some(request) = memory.next(true) {
callback(request)
}
back.set_enabled(memory.back(false).is_some());
this.set_enabled(memory.next(false).is_some());
}
});
// Done
Self {
memory,
back,
forward,
}
}
// Actions
pub fn add(&self, request: GString, follow_to_index: bool) {
self.memory.add(request, follow_to_index);
self.back.set_enabled(self.back(false).is_some());
self.forward.set_enabled(self.forward(false).is_some());
}
pub fn back(&self, follow_to_index: bool) -> Option<GString> {
self.memory.back(follow_to_index)
}
pub fn forward(&self, follow_to_index: bool) -> Option<GString> {
self.memory.next(follow_to_index)
}
}

View file

@ -0,0 +1,13 @@
use gtk::{gio::SimpleAction, glib::uuid_string_random};
pub trait Back {
fn back() -> Self;
}
impl Back for SimpleAction {
fn back() -> Self {
let back = SimpleAction::new(&uuid_string_random(), None);
back.set_enabled(false);
back
}
}

View file

@ -0,0 +1,13 @@
use gtk::{gio::SimpleAction, glib::uuid_string_random};
pub trait Forward {
fn forward() -> Self;
}
impl Forward for SimpleAction {
fn forward() -> Self {
let forward = SimpleAction::new(&uuid_string_random(), None);
forward.set_enabled(false);
forward
}
}

View file

@ -0,0 +1,68 @@
mod cursor;
use cursor::Cursor;
use gtk::glib::GString;
use std::cell::RefCell;
pub struct Memory {
cursor: RefCell<Cursor>,
index: RefCell<Vec<GString>>,
}
impl Memory {
// Constructors
pub fn new() -> Self {
Self {
cursor: RefCell::new(Cursor::new()),
index: RefCell::new(Vec::new()),
}
}
// Actions
pub fn add(&self, value: GString, follow_to_index: bool) {
let mut index = self.index.borrow_mut();
match index.last() {
Some(last) => {
if *last != value {
index.push(value);
}
}
None => index.push(value),
}
if follow_to_index {
self.cursor.borrow_mut().go_last(index.len());
}
}
pub fn back(&self, follow_to_index: bool) -> Option<GString> {
let index = self.index.borrow();
let len = index.len();
match if follow_to_index {
self.cursor.borrow_mut().go_back(len)
} else {
self.cursor.borrow().back(len)
} {
Some(i) => index.get(i).cloned(),
None => None,
}
}
pub fn next(&self, follow_to_index: bool) -> Option<GString> {
let index = self.index.borrow();
let len = index.len();
match if follow_to_index {
self.cursor.borrow_mut().go_next(len)
} else {
self.cursor.borrow().next(len)
} {
Some(i) => index.get(i).cloned(),
None => None,
}
}
}

View file

@ -0,0 +1,66 @@
pub struct Cursor(Option<usize>);
impl Default for Cursor {
fn default() -> Self {
Self::new()
}
}
impl Cursor {
// Constructors
pub fn new() -> Self {
Self(None)
}
// Actions
pub fn go_last(&mut self, len: usize) -> Option<usize> {
self.0 = len2i(len);
self.0
}
pub fn go_next(&mut self, len: usize) -> Option<usize> {
self.0 = self.next(len);
self.0
}
pub fn go_back(&mut self, len: usize) -> Option<usize> {
self.0 = self.back(len);
self.0
}
// Getters
pub fn next(&self, len: usize) -> Option<usize> {
let i = len2i(len)?;
let n = self.0.unwrap_or_default();
if n < i {
Some(n + 1)
} else {
None
}
}
pub fn back(&self, len: usize) -> Option<usize> {
len2i(len)?;
let n = self.0.unwrap_or_default();
if n > 0 {
Some(n - 1)
} else {
None
}
}
}
// Tools
fn len2i(len: usize) -> Option<usize> {
if len > 0 {
Some(len - 1)
} else {
None
}
}