Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 73 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ All configuration is done either at the config file in `XDG_CONFIG_DIR/.config/s

### Shortcuts

#### General
- <kbd>Enter</kbd>: as configured (see below), default: copy-to-clipboard (may be masked by active tool)
- <kbd>Esc</kbd>: as configured (see below), default: exit (may be masked by active tool)
- <kbd>Delete</kbd> reset (clear) <sup>experimental</sup> <sup>0.20.1</sup>
- <kbd>Shift+Delete</kbd> reset (clear) <sup>experimental</sup> <sup>NEXTRELEASE</sup>
- <kbd>Ctrl+C</kbd>: Save to clipboard (may be masked by active tool)
- <kbd>Ctrl+Shift+D</kbd> or <kbd>Ctrl+Shift+I</kbd>: Open GTK inspector if not already opened
- <kbd>Ctrl+S</kbd>: Save to specified output file
Expand Down Expand Up @@ -80,6 +81,7 @@ The bindings are:
- Holding <kbd>Ctrl</kbd> will switch to 1.0 step size
- Mouse <kbd>middle-button</kbd> and <kbd>page up</kbd>/<kbd>page down</kbd> step size is 1.0
- Mouse <kbd>right-button</kbd> jumps to minimum/maximum
- <kbd>s</kbd> focuses the annotation size factor input field

#### Tool Selection Shortcuts (configurable) <sup>0.20.0</sup>
Default single-key shortcuts:
Expand Down Expand Up @@ -131,6 +133,22 @@ Highlight:
- Hold <kbd>Ctrl</kbd> to switch between block and freehand mode (default configurable, see below).
- Hold <kbd>Shift</kbd> in freehand mode for a straight 15° aligned line. Stop at some position and release and hold <kbd>Shift</kbd> again to achieve perfectly aligned turns.

#### Overwriting Keybindings (since NEXTRELEASE)

Shortcuts can be overwritten in the config by
```toml
[keybinds]
"BINDING" = "TOOL-OR-COMMAND"
```

Where `BINDING` follows the GTK syntax. This means modifiers are enclosed in angle brackets (e.g., `<mod>`) and keys are specified by name (for example, `-` must be written as `minus`).

Pressing any unbound key will print its name to the console.

Setting a binding to `"none"` will unbind it.

The defaults are listed in the `config.toml`.

### Configuration File

```toml
Expand Down Expand Up @@ -214,19 +232,60 @@ title = "Satty"
# experimental feature (0.21.0): set app_id, note this has to match D-Bus well-known name format, otherwise GTK does not accept it.
app-id = "org.satty.satty"

# Tool selection keyboard shortcuts (since 0.20.0)
# Generic keyboard shortcuts (NEXTRELEASE)
[keybinds]
pointer = "p"
crop = "c"
brush = "b"
line = "i"
arrow = "z"
rectangle = "r"
ellipse = "e"
text = "t"
marker = "m"
blur = "u"
highlight = "g"
# "<Control>q" = "run-actions-on-escape" # additionally to Escape
# "i" = "none" # unbind "i" default for line
# "l" = "line"

# Global
"<Shift><Control>d" = "open-gtk-inspector"
"<Shift><Control>i" = "open-gtk-inspector"
"<Alt>Left" = "pan-left"
"<Alt>Right" = "pan-right"
"<Alt>Up" = "pan-up"
"<Alt>Down" = "pan-down"
"Delete" = "delete-selection"
"Escape" = "run-actions-on-escape"
"Return" = "run-actions-on-enter"
"<Control>t" = "toggle-toolbars"

# top toolbar
"<Control>1" = "original-scale"
"<Control>2" = "fit-to-window"
"<Shift>Delete" = "reset-all"
"<Control>z" = "undo"
"<Control>y" = "redo"
"p" = "pointer"
"c" = "crop"
"b" = "brush"
"i" = "line"
"z" = "arrow"
"r" = "rectangle"
"e" = "ellipse"
"t" = "text"
"m" = "marker"
"u" = "blur"
"g" = "highlight"
"<Control>s" = "save-to-file"
"<Shift><Control>s" = "save-to-file-as"
"<Control>c" = "save-to-clipboard"
"<Shift><Control>c" = "copy-filepath-to-clipboard"

# bottom toolbar
"1" = "select-color-index:1"
"2" = "select-color-index:2"
"3" = "select-color-index:3"
"4" = "select-color-index:4"
"5" = "select-color-index:5"
"6" = "select-color-index:6"
"7" = "select-color-index:7"
"8" = "select-color-index:8"
"9" = "select-color-index:9"
"minus" = "cycle-size"
#"..." = "select-size:(small|medium|large)"
"s" = "focus-annotation-size-factor"
"f" = "toggle-fill"

# Font to use for text annotations
[font]
Expand Down Expand Up @@ -272,6 +331,7 @@ custom = [
]
```


### Command Line

```
Expand Down
65 changes: 53 additions & 12 deletions config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,60 @@ title = "Satty"
# experimental feature (0.21.0): set app_id, note this has to match D-Bus well-known name format, otherwise GTK does not accept it.
app-id = "org.satty.satty"

# Tool selection keyboard shortcuts (since 0.20.0)
# Generic keyboard shortcuts (NEXTRELEASE)
[keybinds]
pointer = "p"
crop = "c"
brush = "b"
line = "i"
arrow = "z"
rectangle = "r"
ellipse = "e"
text = "t"
marker = "m"
blur = "u"
highlight = "g"
# "<Control>q" = "run-actions-on-escape" # additionally to Escape
# "i" = "none" # unbind "i" default for line
# "l" = "line"

# Global
"<Shift><Control>d" = "open-gtk-inspector"
"<Shift><Control>i" = "open-gtk-inspector"
"<Alt>Left" = "pan-left"
"<Alt>Right" = "pan-right"
"<Alt>Up" = "pan-up"
"<Alt>Down" = "pan-down"
"Delete" = "delete-selection"
"Escape" = "run-actions-on-escape"
"Return" = "run-actions-on-enter"
"<Control>t" = "toggle-toolbars"

# top toolbar
"<Control>1" = "original-scale"
"<Control>2" = "fit-to-window"
"<Shift>Delete" = "reset-all"
"<Control>z" = "undo"
"<Control>y" = "redo"
"p" = "pointer"
"c" = "crop"
"b" = "brush"
"i" = "line"
"z" = "arrow"
"r" = "rectangle"
"e" = "ellipse"
"t" = "text"
"m" = "marker"
"u" = "blur"
"g" = "highlight"
"<Control>s" = "save-to-file"
"<Shift><Control>s" = "save-to-file-as"
"<Control>c" = "save-to-clipboard"
"<Shift><Control>c" = "copy-filepath-to-clipboard"

# bottom toolbar
"1" = "select-color-index:1"
"2" = "select-color-index:2"
"3" = "select-color-index:3"
"4" = "select-color-index:4"
"5" = "select-color-index:5"
"6" = "select-color-index:6"
"7" = "select-color-index:7"
"8" = "select-color-index:8"
"9" = "select-color-index:9"
"minus" = "cycle-size"
#"..." = "select-size:(small|medium|large)"
"s" = "focus-annotation-size-factor"
"f" = "toggle-fill"

# Font to use for text annotations
[font]
Expand Down
106 changes: 8 additions & 98 deletions src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub struct Configuration {
profile_startup: bool,
no_window_decoration: bool,
brush_smooth_history_size: usize,
keybinds: Keybinds,
keybinds: HashMap<String, String>, // key_binding -> tool_or_command
zoom_factor: f32,
pan_step_size: f32,
text_move_length: f32,
Expand All @@ -74,80 +74,6 @@ pub struct Configuration {
app_id: Option<String>,
}

pub struct Keybinds {
shortcuts: HashMap<char, Tools>,
}

impl Keybinds {
pub fn get_tool(&self, key: char) -> Option<Tools> {
self.shortcuts.get(&key).copied()
}

pub fn shortcuts(&self) -> &HashMap<char, Tools> {
&self.shortcuts
}

/// Update a single keybind, only if it is valid
fn update_keybind(&mut self, key: Option<String>, tool: Tools) {
if let Some(key_str) = key
&& let Some(validated_key) = Self::validate_keybind(&key_str, tool)
{
self.shortcuts.retain(|_, v| *v != tool);
self.shortcuts.insert(validated_key, tool);
}
}

/// A shortcut keybinding is only valid if it is one char
fn validate_keybind(key: &str, tool: Tools) -> Option<char> {
let mut chars = key.chars();
match (chars.next(), chars.next()) {
(Some(c), None) => Some(c),
_ => {
eprintln!(
"Warning: Invalid keybind: '{} = {}'. Keybinds must be single characters. Using default keybind instead.",
tool, key
);
None
}
}
}

/// Merge keybindings with default
/// Only replaces defaults if they are set
fn merge(&mut self, file_keybinds: KeybindsFile) {
self.update_keybind(file_keybinds.pointer, Tools::Pointer);
self.update_keybind(file_keybinds.crop, Tools::Crop);
self.update_keybind(file_keybinds.brush, Tools::Brush);
self.update_keybind(file_keybinds.line, Tools::Line);
self.update_keybind(file_keybinds.arrow, Tools::Arrow);
self.update_keybind(file_keybinds.rectangle, Tools::Rectangle);
self.update_keybind(file_keybinds.ellipse, Tools::Ellipse);
self.update_keybind(file_keybinds.text, Tools::Text);
self.update_keybind(file_keybinds.marker, Tools::Marker);
self.update_keybind(file_keybinds.blur, Tools::Blur);
self.update_keybind(file_keybinds.highlight, Tools::Highlight);
}
}

impl Default for Keybinds {
fn default() -> Self {
let mut shortcuts = HashMap::new();
shortcuts.insert('p', Tools::Pointer);
shortcuts.insert('c', Tools::Crop);
shortcuts.insert('b', Tools::Brush);
shortcuts.insert('i', Tools::Line);
shortcuts.insert('z', Tools::Arrow);
shortcuts.insert('r', Tools::Rectangle);
shortcuts.insert('e', Tools::Ellipse);
shortcuts.insert('t', Tools::Text);
shortcuts.insert('m', Tools::Marker);
shortcuts.insert('u', Tools::Blur);
shortcuts.insert('g', Tools::Highlight);

Self { shortcuts }
}
}

#[derive(Default)]
pub struct FontConfiguration {
family: Option<String>,
Expand Down Expand Up @@ -290,7 +216,7 @@ impl From<Vec<EarlyExitTriggers>> for EarlyExit {
}
}

#[derive(Debug, Clone, Copy, Deserialize, PartialEq)]
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub enum Action {
SaveToClipboard,
Expand Down Expand Up @@ -341,6 +267,7 @@ impl Configuration {

APP_CONFIG.write().merge(file, command_line);
}

fn merge_general(&mut self, general: ConfigurationFileGeneral) {
if let Some(v) = general.fullscreen {
self.fullscreen = Some(v);
Expand Down Expand Up @@ -439,6 +366,7 @@ impl Configuration {
}
// ---
}

fn merge(&mut self, file: Option<ConfigurationFile>, command_line: CommandLine) {
// input_filename is required and needs to be overwritten
self.input_filename = command_line.filename;
Expand All @@ -454,9 +382,7 @@ impl Configuration {
if let Some(v) = file.font {
self.font.merge(v);
}
if let Some(v) = file.keybinds {
self.keybinds.merge(v);
}
self.keybinds = file.keybinds.unwrap_or_default();
}

// overwrite with all specified values from command line
Expand Down Expand Up @@ -691,7 +617,7 @@ impl Configuration {
self.brush_smooth_history_size
}

pub fn keybinds(&self) -> &Keybinds {
pub fn keybinds(&self) -> &HashMap<String, String> {
&self.keybinds
}

Expand Down Expand Up @@ -750,7 +676,7 @@ impl Default for Configuration {
profile_startup: false,
no_window_decoration: false,
brush_smooth_history_size: 0, // default to 0, no history
keybinds: Keybinds::default(),
keybinds: HashMap::new(),
zoom_factor: 1.1,
pan_step_size: 50.,
text_move_length: 50.0,
Expand Down Expand Up @@ -782,23 +708,7 @@ struct ConfigurationFile {
general: Option<ConfigurationFileGeneral>,
color_palette: Option<ColorPaletteFile>,
font: Option<FontFile>,
keybinds: Option<KeybindsFile>,
}

#[derive(Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
struct KeybindsFile {
pointer: Option<String>,
crop: Option<String>,
brush: Option<String>,
line: Option<String>,
arrow: Option<String>,
rectangle: Option<String>,
ellipse: Option<String>,
text: Option<String>,
marker: Option<String>,
blur: Option<String>,
highlight: Option<String>,
keybinds: Option<HashMap<String, String>>,
}

#[derive(Deserialize)]
Expand Down
Loading
Loading