Skip to content

Commit

Permalink
Add forward/back view functionality for mouse side buttons
Browse files Browse the repository at this point in the history
 * Allows users to navigate forward/back between views and subgraphs
 * Add `PlaceholderInput` to match `PlaceholderOutput` and get it minimally working
  • Loading branch information
Ameobea committed Feb 9, 2024
1 parent 95a33f7 commit bc3cc15
Show file tree
Hide file tree
Showing 14 changed files with 481 additions and 72 deletions.
28 changes: 19 additions & 9 deletions engine/engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,22 @@ extern crate log;

use std::{ptr, str::FromStr};

use prelude::js::js_random;
use common::uuid_v4;
use js::js_random;
use uuid::Uuid;
use view_context::manager::{ConnectionDescriptor, ViewContextManager};
use wasm_bindgen::prelude::*;

pub mod js;
pub mod prelude;
pub mod view_context;
pub mod views;
use crate::{
prelude::*,
view_context::manager::{build_view, ForeignConnectable},
};
use crate::view_context::manager::{build_view, ForeignConnectable};

/// The global view context manager that holds all of the view contexts for the application.
static mut VIEW_CONTEXT_MANAGER: *mut ViewContextManager = ptr::null_mut();

/// Retrieves the global `ViewContextManager` for the application
pub fn get_vcm() -> &'static mut ViewContextManager {
pub(crate) fn get_vcm() -> &'static mut ViewContextManager {
if cfg!(debug_assertions) && unsafe { VIEW_CONTEXT_MANAGER.is_null() } {
panic!("VIEW_CONTEXT_MANAGER is null");
}
Expand Down Expand Up @@ -88,7 +86,7 @@ pub fn delete_vc_by_id(id: &str) {
pub fn switch_view_context(uuid_str: &str) {
let uuid =
Uuid::from_str(uuid_str).expect("Invalid UUID string passed to `switch_view_context`!");
get_vcm().set_active_view(uuid);
get_vcm().set_active_view(uuid, false);
}

#[wasm_bindgen]
Expand All @@ -98,14 +96,26 @@ pub fn add_subgraph() -> String {
new_subgraph_id.to_string()
}

#[wasm_bindgen]
pub fn delete_subgraph(subgraph_id: &str) {
let uuid = Uuid::from_str(subgraph_id).expect("Invalid UUID string passed to `delete_subgraph`!");
get_vcm().delete_subgraph(uuid);
}

#[wasm_bindgen]
pub fn set_active_subgraph_id(subgraph_id: &str) {
let uuid =
Uuid::from_str(subgraph_id).expect("Invalid UUID string passed to `set_active_subgraph_id`!");
let vcm = get_vcm();
vcm.set_active_subgraph(uuid);
vcm.set_active_subgraph(uuid, false);
}

#[wasm_bindgen]
pub fn undo_view_change() { get_vcm().undo_view_change(); }

#[wasm_bindgen]
pub fn redo_view_change() { get_vcm().redo_view_change(); }

#[wasm_bindgen]
pub fn reset_vcm() {
info!("Resetting VCM...");
Expand Down
15 changes: 0 additions & 15 deletions engine/engine/src/prelude.rs

This file was deleted.

164 changes: 164 additions & 0 deletions engine/engine/src/view_context/active_view_history.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
use std::collections::VecDeque;

use serde::{Deserialize, Serialize};
use uuid::Uuid;

const ACTIVE_VIEW_HISTORY_LEN: usize = 20;

#[derive(Clone, Serialize, Deserialize, Debug)]
pub(crate) struct ActiveView {
pub subgraph_id: Uuid,
pub vc_id: Uuid,
}

#[derive(Clone, Serialize, Deserialize, Debug)]
pub(crate) struct ActiveViewHistory {
pub(crate) history: VecDeque<ActiveView>,
/// Points to one past the last element in the history
pub(crate) index: usize,
}

impl Default for ActiveViewHistory {
fn default() -> Self {
Self {
history: VecDeque::with_capacity(ACTIVE_VIEW_HISTORY_LEN),
index: 0,
}
}
}

impl ActiveViewHistory {
pub fn set_active_view(&mut self, subgraph_id: Uuid, vc_id: Uuid) {
self.history.truncate(self.index);
self.history.push_back(ActiveView { subgraph_id, vc_id });
self.index += 1;

if self.history.len() > ACTIVE_VIEW_HISTORY_LEN {
self.history.pop_front();
self.index -= 1;
}
}

pub fn undo(&mut self) -> Option<ActiveView> {
if self.index > 1 {
self.index -= 1;
self.history.get(self.index - 1).cloned()
} else {
None
}
}

pub fn redo(&mut self) -> Option<ActiveView> {
if self.index < self.history.len() {
self.index += 1;
self.history.get(self.index - 1).cloned()
} else {
None
}
}

pub fn clear(&mut self, cur_active_subgraph_id: Uuid, cur_active_vc_id: Uuid) {
self.history.clear();
self.index = 0;
self.set_active_view(cur_active_subgraph_id, cur_active_vc_id);
}

pub fn filter(&mut self, cb: impl Fn(&ActiveView) -> bool) {
let mut i = 0;
while i < self.history.len() {
if !cb(&self.history[i]) {
self.history.remove(i);

if self.index > i {
self.index -= 1;
}
}

i += 1;
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_active_view_history() {
let mut history = ActiveViewHistory::default();
assert_eq!(history.history.len(), 0);
assert_eq!(history.index, 0);

history.set_active_view(Uuid::from_bytes([1; 16]), Uuid::nil());
assert_eq!(history.history.len(), 1);
assert_eq!(history.index, 1);

history.set_active_view(Uuid::from_bytes([2; 16]), Uuid::nil());
assert_eq!(history.history.len(), 2);
assert_eq!(history.index, 2);

let view = history.undo().unwrap();
assert_eq!(history.index, 1);
assert_eq!(view.subgraph_id, Uuid::from_bytes([1; 16]));

let view = history.undo();
assert_eq!(history.index, 1);
assert!(view.is_none());

let view = history.undo();
assert_eq!(history.index, 1);
assert!(view.is_none());

let view = history.redo().unwrap();
assert_eq!(history.index, 2);
assert_eq!(view.subgraph_id, Uuid::from_bytes([2; 16]));

let view = history.redo();
assert_eq!(history.index, 2);
assert!(view.is_none());
}

#[test]
fn history_filter() {
let zero = Uuid::from_bytes([0; 16]);
let one = Uuid::from_bytes([1; 16]);
let two = Uuid::from_bytes([2; 16]);

let mut history = ActiveViewHistory::default();

history.set_active_view(zero, zero);
history.set_active_view(one, one);
history.set_active_view(two, two);

history.filter(|view| view.subgraph_id != one);
assert_eq!(history.history.len(), 2);

let view = history.undo().unwrap();
assert_eq!(view.subgraph_id, zero);

let view = history.undo();
assert!(view.is_none());

let view = history.redo().unwrap();
assert_eq!(view.subgraph_id, two);
}

#[test]
fn history_filter_2() {
let zero = Uuid::from_bytes([0; 16]);
let one = Uuid::from_bytes([1; 16]);
let two = Uuid::from_bytes([2; 16]);

let mut history = ActiveViewHistory::default();

history.set_active_view(zero, zero);
history.set_active_view(one, one);

history.filter(|view| view.subgraph_id != zero);

history.set_active_view(two, two);

let view = history.undo().unwrap();
assert_eq!(view.subgraph_id, one);
}
}
Loading

0 comments on commit bc3cc15

Please sign in to comment.