livesplit_core/
hotkey_config.rs1#![allow(clippy::trivially_copy_pass_by_ref)]
2
3use crate::{
4 hotkey::Hotkey,
5 platform::prelude::*,
6 settings::{Field, SettingsDescription, Value},
7};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
12#[serde(default)]
13pub struct HotkeyConfig {
14 pub split: Option<Hotkey>,
16 pub reset: Option<Hotkey>,
18 pub undo: Option<Hotkey>,
20 pub skip: Option<Hotkey>,
22 pub pause: Option<Hotkey>,
25 pub undo_all_pauses: Option<Hotkey>,
27 pub previous_comparison: Option<Hotkey>,
29 pub next_comparison: Option<Hotkey>,
31 pub toggle_timing_method: Option<Hotkey>,
34}
35
36impl Default for HotkeyConfig {
37 fn default() -> Self {
38 use crate::hotkey::KeyCode::*;
39 Self {
40 split: Some(Numpad1.into()),
41 reset: Some(Numpad3.into()),
42 undo: Some(Numpad8.into()),
43 skip: Some(Numpad2.into()),
44 pause: Some(Numpad5.into()),
45 undo_all_pauses: None,
46 previous_comparison: Some(Numpad4.into()),
47 next_comparison: Some(Numpad6.into()),
48 toggle_timing_method: None,
49 }
50 }
51}
52
53impl HotkeyConfig {
54 pub fn settings_description(&self) -> SettingsDescription {
57 SettingsDescription::with_fields(vec![
58 Field::new("Start / Split".into(), self.split.into()),
59 Field::new("Reset".into(), self.reset.into()),
60 Field::new("Undo Split".into(), self.undo.into()),
61 Field::new("Skip Split".into(), self.skip.into()),
62 Field::new("Pause".into(), self.pause.into()),
63 Field::new("Undo All Pauses".into(), self.undo_all_pauses.into()),
64 Field::new(
65 "Previous Comparison".into(),
66 self.previous_comparison.into(),
67 ),
68 Field::new("Next Comparison".into(), self.next_comparison.into()),
69 Field::new(
70 "Toggle Timing Method".into(),
71 self.toggle_timing_method.into(),
72 ),
73 ])
74 }
75
76 pub fn set_value(&mut self, index: usize, value: Value) -> Result<(), ()> {
89 let value: Option<Hotkey> = value.into();
90
91 if value.is_some() {
92 let any = [
93 self.split,
94 self.reset,
95 self.undo,
96 self.skip,
97 self.pause,
98 self.undo_all_pauses,
99 self.previous_comparison,
100 self.next_comparison,
101 self.toggle_timing_method,
102 ]
103 .into_iter()
104 .enumerate()
105 .filter(|&(i, _)| i != index)
106 .any(|(_, v)| v == value);
107
108 if any {
109 return Err(());
110 }
111 }
112
113 match index {
114 0 => self.split = value,
115 1 => self.reset = value,
116 2 => self.undo = value,
117 3 => self.skip = value,
118 4 => self.pause = value,
119 5 => self.undo_all_pauses = value,
120 6 => self.previous_comparison = value,
121 7 => self.next_comparison = value,
122 8 => self.toggle_timing_method = value,
123 _ => panic!("Unsupported Setting Index"),
124 }
125
126 Ok(())
127 }
128
129 #[cfg(feature = "std")]
131 pub fn from_json<R>(reader: R) -> serde_json::Result<Self>
132 where
133 R: std::io::Read,
134 {
135 serde_json::from_reader(reader)
136 }
137
138 #[cfg(feature = "std")]
140 pub fn write_json<W>(&self, writer: W) -> serde_json::Result<()>
141 where
142 W: std::io::Write,
143 {
144 serde_json::to_writer(writer, self)
145 }
146}