layout: Make it possible to opt out of latching per-key
This commit is contained in:
		@ -29,6 +29,9 @@ pub enum Action {
 | 
			
		||||
        lock: View,
 | 
			
		||||
        /// When unlocked by pressing it or emitting a key
 | 
			
		||||
        unlock: View,
 | 
			
		||||
        /// Whether key has a latched state
 | 
			
		||||
        /// that pops when another key is pressed.
 | 
			
		||||
        latches: bool,
 | 
			
		||||
    },
 | 
			
		||||
    /// Hold this modifier for as long as the button is pressed
 | 
			
		||||
    ApplyModifier(Modifier),
 | 
			
		||||
@ -48,14 +51,14 @@ pub enum Action {
 | 
			
		||||
impl Action {
 | 
			
		||||
    pub fn is_locked(&self, view_name: &str) -> bool {
 | 
			
		||||
        match self {
 | 
			
		||||
            Action::LockView { lock, unlock: _ } => lock == view_name,
 | 
			
		||||
            Action::LockView { lock, unlock: _, latches: _ } => lock == view_name,
 | 
			
		||||
            _ => false,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pub fn is_active(&self, view_name: &str) -> bool {
 | 
			
		||||
        match self {
 | 
			
		||||
            Action::SetView(view) => view == view_name,
 | 
			
		||||
            Action::LockView { lock, unlock: _ } => lock == view_name,
 | 
			
		||||
            Action::LockView { lock, unlock: _, latches: _ } => lock == view_name,
 | 
			
		||||
            _ => false,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								src/data.rs
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/data.rs
									
									
									
									
									
								
							@ -266,7 +266,11 @@ struct ButtonMeta {
 | 
			
		||||
#[serde(deny_unknown_fields)]
 | 
			
		||||
enum Action {
 | 
			
		||||
    #[serde(rename="locking")]
 | 
			
		||||
    Locking { lock_view: String, unlock_view: String },
 | 
			
		||||
    Locking {
 | 
			
		||||
        lock_view: String,
 | 
			
		||||
        unlock_view: String,
 | 
			
		||||
        pops: Option<bool>,
 | 
			
		||||
    },
 | 
			
		||||
    #[serde(rename="set_view")]
 | 
			
		||||
    SetView(String),
 | 
			
		||||
    #[serde(rename="show_prefs")]
 | 
			
		||||
@ -577,7 +581,8 @@ fn create_action<H: logging::Handler>(
 | 
			
		||||
            )
 | 
			
		||||
        ),
 | 
			
		||||
        SubmitData::Action(Action::Locking {
 | 
			
		||||
            lock_view, unlock_view
 | 
			
		||||
            lock_view, unlock_view,
 | 
			
		||||
            pops,
 | 
			
		||||
        }) => ::action::Action::LockView {
 | 
			
		||||
            lock: filter_view_name(
 | 
			
		||||
                name,
 | 
			
		||||
@ -591,6 +596,7 @@ fn create_action<H: logging::Handler>(
 | 
			
		||||
                &view_names,
 | 
			
		||||
                warning_handler,
 | 
			
		||||
            ),
 | 
			
		||||
            latches: pops.unwrap_or(true),
 | 
			
		||||
        },
 | 
			
		||||
        SubmitData::Action(
 | 
			
		||||
            Action::ShowPrefs
 | 
			
		||||
 | 
			
		||||
@ -830,14 +830,14 @@ impl Layout {
 | 
			
		||||
    fn process_action_for_view<'a>(
 | 
			
		||||
        action: &'a Action,
 | 
			
		||||
        current_view: &str,
 | 
			
		||||
        latch: &LatchedState,
 | 
			
		||||
        latched: &LatchedState,
 | 
			
		||||
    ) -> (ViewTransition<'a>, LatchedState) {
 | 
			
		||||
        match action {
 | 
			
		||||
            Action::Submit { text: _, keys: _ }
 | 
			
		||||
                | Action::Erase
 | 
			
		||||
                | Action::ApplyModifier(_)
 | 
			
		||||
            => {
 | 
			
		||||
                let t = match latch {
 | 
			
		||||
                let t = match latched {
 | 
			
		||||
                    LatchedState::FromView(_) => ViewTransition::UnlatchAll,
 | 
			
		||||
                    LatchedState::Not => ViewTransition::NoChange,
 | 
			
		||||
                };
 | 
			
		||||
@ -847,29 +847,32 @@ impl Layout {
 | 
			
		||||
                ViewTransition::ChangeTo(view),
 | 
			
		||||
                LatchedState::Not,
 | 
			
		||||
            ),
 | 
			
		||||
            Action::LockView { lock, unlock } => {
 | 
			
		||||
            Action::LockView { lock, unlock, latches } => {
 | 
			
		||||
                use self::ViewTransition as VT;
 | 
			
		||||
                let locked = action.is_locked(current_view);
 | 
			
		||||
                match (locked, latch) {
 | 
			
		||||
                match (locked, latched, latches) {
 | 
			
		||||
                    // Was unlocked, now make locked but latched.
 | 
			
		||||
                    (false, LatchedState::Not) => (
 | 
			
		||||
                    (false, LatchedState::Not, true) => (
 | 
			
		||||
                        VT::ChangeTo(lock),
 | 
			
		||||
                        LatchedState::FromView(current_view.into()),
 | 
			
		||||
                    ),
 | 
			
		||||
                    // Layout is latched for reason other than this button.
 | 
			
		||||
                    (false, LatchedState::FromView(view)) => (
 | 
			
		||||
                    (false, LatchedState::FromView(view), true) => (
 | 
			
		||||
                        VT::ChangeTo(lock),
 | 
			
		||||
                        LatchedState::FromView(view.clone()),
 | 
			
		||||
                    ),
 | 
			
		||||
                    // Was latched, now only locked.
 | 
			
		||||
                    (true, LatchedState::FromView(_))
 | 
			
		||||
                    (true, LatchedState::FromView(_), true)
 | 
			
		||||
                        => (VT::NoChange, LatchedState::Not),
 | 
			
		||||
                    // Was unlocked, can't latch so now make fully locked.
 | 
			
		||||
                    (false, _, false)
 | 
			
		||||
                        => (VT::ChangeTo(lock), LatchedState::Not),
 | 
			
		||||
                    // Was locked, now make unlocked.
 | 
			
		||||
                    (true, LatchedState::Not)
 | 
			
		||||
                    (true, _, _)
 | 
			
		||||
                        => (VT::ChangeTo(unlock), LatchedState::Not),
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            _ => (ViewTransition::NoChange, latch.clone()),
 | 
			
		||||
            _ => (ViewTransition::NoChange, latched.clone()),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1128,6 +1131,7 @@ mod test {
 | 
			
		||||
        let action = Action::LockView {
 | 
			
		||||
            lock: "lock".into(),
 | 
			
		||||
            unlock: "unlock".into(),
 | 
			
		||||
            latches: true,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
@ -1156,6 +1160,7 @@ mod test {
 | 
			
		||||
        let switch = Action::LockView {
 | 
			
		||||
            lock: "locked".into(),
 | 
			
		||||
            unlock: "base".into(),
 | 
			
		||||
            latches: true,
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        let submit = Action::Erase;
 | 
			
		||||
@ -1217,16 +1222,82 @@ mod test {
 | 
			
		||||
        assert_eq!(&layout.current_view, "base");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn reverse_unlatch_layout() {
 | 
			
		||||
        let switch = Action::LockView {
 | 
			
		||||
            lock: "locked".into(),
 | 
			
		||||
            unlock: "base".into(),
 | 
			
		||||
            latches: true,
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        let unswitch = Action::LockView {
 | 
			
		||||
            lock: "locked".into(),
 | 
			
		||||
            unlock: "unlocked".into(),
 | 
			
		||||
            latches: false,
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        let submit = Action::Erase;
 | 
			
		||||
 | 
			
		||||
        let view = View::new(vec![(
 | 
			
		||||
            0.0,
 | 
			
		||||
            Row::new(vec![
 | 
			
		||||
                (
 | 
			
		||||
                    0.0,
 | 
			
		||||
                    make_button_with_state(
 | 
			
		||||
                        "switch".into(),
 | 
			
		||||
                        make_state_with_action(switch.clone())
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    1.0,
 | 
			
		||||
                    make_button_with_state(
 | 
			
		||||
                        "submit".into(),
 | 
			
		||||
                        make_state_with_action(submit.clone())
 | 
			
		||||
                    ),
 | 
			
		||||
                ),
 | 
			
		||||
            ]),
 | 
			
		||||
        )]);
 | 
			
		||||
 | 
			
		||||
        let mut layout = Layout {
 | 
			
		||||
            current_view: "base".into(),
 | 
			
		||||
            view_latched: LatchedState::Not,
 | 
			
		||||
            keymaps: Vec::new(),
 | 
			
		||||
            kind: ArrangementKind::Base,
 | 
			
		||||
            pressed_keys: HashSet::new(),
 | 
			
		||||
            margins: Margins {
 | 
			
		||||
                top: 0.0,
 | 
			
		||||
                left: 0.0,
 | 
			
		||||
                right: 0.0,
 | 
			
		||||
                bottom: 0.0,
 | 
			
		||||
            },
 | 
			
		||||
            views: hashmap! {
 | 
			
		||||
                // Both can use the same structure.
 | 
			
		||||
                // Switching doesn't depend on the view shape
 | 
			
		||||
                // as long as the switching button is present.
 | 
			
		||||
                "base".into() => (c::Point { x: 0.0, y: 0.0 }, view.clone()),
 | 
			
		||||
                "locked".into() => (c::Point { x: 0.0, y: 0.0 }, view.clone()),
 | 
			
		||||
                "unlocked".into() => (c::Point { x: 0.0, y: 0.0 }, view),
 | 
			
		||||
            },
 | 
			
		||||
        };        
 | 
			
		||||
 | 
			
		||||
        layout.apply_view_transition(&switch);
 | 
			
		||||
        assert_eq!(&layout.current_view, "locked");
 | 
			
		||||
        layout.apply_view_transition(&unswitch);
 | 
			
		||||
        assert_eq!(&layout.current_view, "unlocked");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn latch_twopop_layout() {
 | 
			
		||||
        let switch = Action::LockView {
 | 
			
		||||
            lock: "locked".into(),
 | 
			
		||||
            unlock: "base".into(),
 | 
			
		||||
            latches: true,
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        let switch_again = Action::LockView {
 | 
			
		||||
            lock: "ĄĘ".into(),
 | 
			
		||||
            unlock: "locked".into(),
 | 
			
		||||
            latches: true,
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        let submit = Action::Erase;
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user