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