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!(cmd_list_logs, "listlogs");
|
||||||
register_command!(mud_log, "log");
|
register_command!(mud_log, "log");
|
||||||
register_command!(panel_merge);
|
register_command!(panel_merge);
|
||||||
|
register_command!(panel_swap);
|
||||||
register_command!(sendmud_raw);
|
register_command!(sendmud_raw);
|
||||||
register_stateless_command!(storage);
|
register_stateless_command!(storage);
|
||||||
register_command!(tick);
|
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>(
|
pub fn try_unwrap_frame<'gc>(
|
||||||
ctx: Context<'gc>,
|
ctx: Context<'gc>,
|
||||||
value: &Value<'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> {
|
pub fn hsplit(&self, pathstr: &str, new_frame: FrameId) -> Result<TermSplit, String> {
|
||||||
let new = self.modify_at_pathstr(pathstr, move |n| {
|
let new = self.modify_at_pathstr(pathstr, move |n| {
|
||||||
Ok(TermSplit::Horizontal {
|
Ok(TermSplit::Horizontal {
|
||||||
@ -143,6 +168,17 @@ impl TermSplit {
|
|||||||
TermSplit::Vertical { top, .. } => Ok((**top).clone()),
|
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> {
|
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