diff options
| author | Arne Dußin | 2021-01-27 14:01:50 +0100 |
|---|---|---|
| committer | Arne Dußin | 2021-02-02 22:16:15 +0100 |
| commit | f92e9f6f07b1e3834c2ca58ce3510734819d08e4 (patch) | |
| tree | 20e3d3afce342a56ae98f6c20491482ccd2b5c6b /src/client/config.rs | |
| parent | c60a6d07efb120724b308e29e8e70f27c87c952d (diff) | |
| download | graf_karto-f92e9f6f07b1e3834c2ca58ce3510734819d08e4.tar.gz graf_karto-f92e9f6f07b1e3834c2ca58ce3510734819d08e4.zip | |
Rework graf karto to fit the client/server structure
Diffstat (limited to 'src/client/config.rs')
| -rw-r--r-- | src/client/config.rs | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/client/config.rs b/src/client/config.rs new file mode 100644 index 0000000..96ff3f5 --- /dev/null +++ b/src/client/config.rs @@ -0,0 +1,166 @@ +//! Home of the user configuratable content of graf karto, like keybindings and (TODO) colours etc. + +use crate::client::input::{Binding, Button, Input, MouseButton, Scancode}; +use ron::de::from_reader; +use ron::ser::{to_string_pretty, PrettyConfig}; +use serde::{Deserialize, Serialize}; +use std::fs::File; +use std::io::{self, Write}; +use std::path::Path; + +/// All configuration parameters the user can set are contained in this struct. +#[allow(missing_docs)] +#[derive(Deserialize, Serialize)] +pub struct Config { + pub tool_activation_binds: ToolActivationBinds, + pub tool_general_binds: ToolGeneralBinds, + pub icon_binds: IconToolBinds, +} + +#[allow(missing_docs)] +#[derive(Deserialize, Serialize)] +/// The keys used to activate the individual tools. These keystrokes will not be sent to the tools, +/// but instead will be handled by the editor where the tools are registered. +pub struct ToolActivationBinds { + pub deletion: Binding, + pub icon: Binding, + pub polygon_room: Binding, + pub rect_room: Binding, + pub selection: Binding, + pub wall: Binding, +} + +#[derive(Deserialize, Serialize)] +/// Keys that are useful to most tools. These are packaged so that not every tool has the same n keys +/// and then some more. +pub struct ToolGeneralBinds { + /// Keybinding to, where applicable, place a single node (usually a vertex) for the tool in + /// question. + pub place_single: Binding, + /// Finish up whatever one is doing with the current tool, without removing information. + pub finish: Binding, + /// Abort whatever one is doing with the current tool which means the last atomic action will not + /// be pushed into the map items. + pub abort: Binding, +} + +#[derive(Clone, Serialize, Deserialize)] +/// Key bindings that are individually interesting to the icon tool. +pub struct IconToolBinds { + /// Key to change to the next icon of the icon list. + pub next: Binding, + /// Key to change to the previous icon of the icon list. + pub previous: Binding, + /// Rotate the working icon clockwise by a certain amount (currently 45 degrees) + pub rotate_clockwise: Binding, + /// Rotate the working icon counterclockwise by a certain amount (currently 45 degrees) + pub rotate_counterclockwise: Binding, +} + +impl Config { + /// Try to parse a configuration from the file located at path. + /// + /// # Errors + /// If the file is not found or can not be read or parsed for a different reason, an IO-Error is + /// returned. + pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Config> { + let file = File::open(&path)?; + match from_reader(file) { + Ok(data) => Ok(data), + Err(err) => Err(io::Error::new(io::ErrorKind::InvalidData, err)), + } + } + + /// Try to write the configuration to the file at path. If the file exists, it will be overwritten. + /// + /// # Errors + /// If the file can not be written, for example for lack of permissions, an IO-Error is returned. + pub fn write_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> { + let mut file = File::create(&path)?; + + let pretty_conf = PrettyConfig::new() + .with_depth_limit(4) + .with_decimal_floats(true) + .with_separate_tuple_members(true) + .with_indentor("\t".to_owned()); + let string = match to_string_pretty(&self, pretty_conf) { + Ok(string) => string, + Err(err) => { + return Err(io::Error::new(io::ErrorKind::InvalidInput, err)); + } + }; + + file.write_all(&string.as_bytes()) + } +} + +/// Registers all bindings from the given configuration into the input handler. Should the +/// configuration change at runtime, the global bindings of the input handler need to be cleared and +/// this function must be called again. +pub fn register_bindings(config: &Config, input: &mut Input) { + if !input.add_global(config.tool_activation_binds.deletion.clone()) { + warn!("Tried to add deletion binding twice."); + } + if !input.add_global(config.tool_activation_binds.icon.clone()) { + warn!("Tried to add icon binding twice."); + } + if !input.add_global(config.tool_activation_binds.polygon_room.clone()) { + warn!("Tried to add polygon room binding twice."); + } + if !input.add_global(config.tool_activation_binds.rect_room.clone()) { + warn!("Tried to add rect room binding twice."); + } + if !input.add_global(config.tool_activation_binds.selection.clone()) { + warn!("Tried to add selection binding twice."); + } + if !input.add_global(config.tool_activation_binds.wall.clone()) { + warn!("Tried to add wall binding twice."); + } + if !input.add_global(config.tool_general_binds.place_single.clone()) { + warn!("Tried to add place single binding twice."); + } + if !input.add_global(config.tool_general_binds.finish.clone()) { + warn!("Tried to add finish binding twice."); + } + if !input.add_global(config.tool_general_binds.abort.clone()) { + warn!("Tried to add abort binding twice."); + } + if !input.add_global(config.icon_binds.next.clone()) { + warn!("Tried to add next binding twice."); + } + if !input.add_global(config.icon_binds.previous.clone()) { + warn!("Tried to add previous binding twice."); + } + if !input.add_global(config.icon_binds.rotate_clockwise.clone()) { + warn!("Tried to add rotate clockwise binding twice."); + } + if !input.add_global(config.icon_binds.rotate_counterclockwise.clone()) { + warn!("Tried to add rotate counterclockwise binding twice."); + } +} + +impl Default for Config { + fn default() -> Self { + Config { + tool_activation_binds: ToolActivationBinds { + deletion: Button::Text('d').into(), + icon: Button::Text('i').into(), + polygon_room: Button::Text('p').into(), + rect_room: Button::Text('r').into(), + selection: Button::Text('s').into(), + wall: Button::Text('w').into(), + }, + tool_general_binds: ToolGeneralBinds { + place_single: Button::Mouse(MouseButton::Left).into(), + finish: Button::Scancode(Scancode::Enter).into(), + abort: Button::Mouse(MouseButton::Right).into(), + }, + icon_binds: IconToolBinds { + next: Button::Text('j').into(), + previous: Button::Text('k').into(), + rotate_clockwise: Button::Text('+').into(), + rotate_counterclockwise: Button::Text('-').into(), + }, + } + } +} |
