Implement swapping panels
This commit is contained in:
parent
b36bcbf2ac
commit
13225859a1
@ -227,6 +227,7 @@ pub fn install_lua_globals(
|
||||
register_command!(cmd_list_logs, "listlogs");
|
||||
register_command!(mud_log, "log");
|
||||
register_command!(panel_merge);
|
||||
register_command!(panel_swap);
|
||||
register_command!(sendmud_raw);
|
||||
register_stateless_command!(storage);
|
||||
register_command!(tick);
|
||||
|
@ -290,6 +290,32 @@ pub fn panel_merge<'gc>(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn panel_swap<'gc>(
|
||||
ctx: Context<'gc>,
|
||||
global_memo: &GlobalMemoCell,
|
||||
global_layout: &UseStateSetter<GlobalLayoutCell>,
|
||||
) -> Callback<'gc> {
|
||||
let global_layout = global_layout.clone();
|
||||
let global_memo = global_memo.clone();
|
||||
Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
|
||||
let path1: String = stack.from_front(ctx)?;
|
||||
let path2: String = stack.from_front(ctx)?;
|
||||
let new_splits = global_memo
|
||||
.layout
|
||||
.borrow()
|
||||
.term_splits
|
||||
.swap(&path1, &path2)
|
||||
.map_err(|e| e.into_value(ctx))?;
|
||||
let new_layout = Rc::new(GlobalLayoutState {
|
||||
term_splits: new_splits.clone(),
|
||||
..(*(global_memo.layout.borrow().as_ref())).clone()
|
||||
});
|
||||
global_layout.set(new_layout.clone());
|
||||
*(global_memo.layout.borrow_mut()) = new_layout;
|
||||
Ok(piccolo::CallbackReturn::Return)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn try_unwrap_frame<'gc>(
|
||||
ctx: Context<'gc>,
|
||||
value: &Value<'gc>,
|
||||
|
@ -112,6 +112,31 @@ impl TermSplit {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_at_pathstr(&self, pathstr: &str) -> Result<&Self, String> {
|
||||
self.get_at_pathstr_vec(&pathstr.chars().collect::<Vec<char>>())
|
||||
}
|
||||
|
||||
fn get_at_pathstr_vec(&self, pathstr: &[char]) -> Result<&Self, String> {
|
||||
match self {
|
||||
TermSplit::Horizontal { left, right } => match pathstr.split_first() {
|
||||
None => Ok(self),
|
||||
Some(('l', path_rest)) => left.get_at_pathstr_vec(path_rest),
|
||||
Some(('r', path_rest)) => right.get_at_pathstr_vec(path_rest),
|
||||
Some((c, path_rest)) => Err(format!("In split path, found {} before {}, which was unexpected for a horizontal split", c, path_rest.iter().collect::<String>()))
|
||||
},
|
||||
TermSplit::Vertical { top, bottom } => match pathstr.split_first() {
|
||||
None => Ok(self),
|
||||
Some(('t', path_rest)) => top.get_at_pathstr_vec(path_rest),
|
||||
Some(('b', path_rest)) => bottom.get_at_pathstr_vec(path_rest),
|
||||
Some((c, path_rest)) => Err(format!("In split path, found {} before {}, which was unexpected for a vertical split", c, path_rest.iter().collect::<String>()))
|
||||
},
|
||||
TermSplit::Term { .. } => match pathstr.split_first() {
|
||||
None => Ok(self),
|
||||
Some(_) => Err(format!("In split path, found trailing junk {} after addressing terminal", pathstr.iter().collect::<String>()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hsplit(&self, pathstr: &str, new_frame: FrameId) -> Result<TermSplit, String> {
|
||||
let new = self.modify_at_pathstr(pathstr, move |n| {
|
||||
Ok(TermSplit::Horizontal {
|
||||
@ -143,6 +168,17 @@ impl TermSplit {
|
||||
TermSplit::Vertical { top, .. } => Ok((**top).clone()),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn swap(&self, pathstr1: &str, pathstr2: &str) -> Result<TermSplit, String> {
|
||||
let split1 = self.get_at_pathstr(pathstr1)?;
|
||||
let split2 = self.get_at_pathstr(pathstr2)?;
|
||||
let new = self
|
||||
.modify_at_pathstr(pathstr1, |_t| Ok(split2.clone()))?
|
||||
.modify_at_pathstr(pathstr2, |_t| Ok(split1.clone()))?;
|
||||
// It can fail if one path nests the other.
|
||||
new.validate()?;
|
||||
Ok(new)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AccessibleSplitIter<'t> {
|
||||
@ -303,4 +339,44 @@ mod tests {
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn swapping_works() {
|
||||
use TermSplit::*;
|
||||
let t = Vertical {
|
||||
top: Horizontal {
|
||||
left: Horizontal {
|
||||
left: Term { frame: FrameId(42) }.into(),
|
||||
right: Term { frame: FrameId(64) }.into(),
|
||||
}
|
||||
.into(),
|
||||
right: Term { frame: FrameId(46) }.into(),
|
||||
}
|
||||
.into(),
|
||||
bottom: Vertical {
|
||||
top: Term { frame: FrameId(43) }.into(),
|
||||
bottom: Term { frame: FrameId(44) }.into(),
|
||||
}
|
||||
.into(),
|
||||
};
|
||||
assert_eq!(
|
||||
t.swap("tl", "b"),
|
||||
Ok(Vertical {
|
||||
top: Horizontal {
|
||||
left: Vertical {
|
||||
top: Term { frame: FrameId(43) }.into(),
|
||||
bottom: Term { frame: FrameId(44) }.into(),
|
||||
}
|
||||
.into(),
|
||||
right: Term { frame: FrameId(46) }.into(),
|
||||
}
|
||||
.into(),
|
||||
bottom: Horizontal {
|
||||
left: Term { frame: FrameId(42) }.into(),
|
||||
right: Term { frame: FrameId(64) }.into(),
|
||||
}
|
||||
.into(),
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user