summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2022-08-27 21:45:19 +0200
committerPhilipp Gesang <phg@phi-gamma.net>2022-08-27 22:40:44 +0200
commitddeb59a89092b0bd7e7b77e3c71dc9bace1e23e5 (patch)
tree17790540394c40511be8911ba62281a00f75d77f /src
parentc4473f41f22d1e9de1b38e2cb6700410d71e3712 (diff)
downloadvtcol-ddeb59a89092b0bd7e7b77e3c71dc9bace1e23e5.tar.gz
edit: implement the actual save operation
We save palettes in the format that can be directly re-parsed by vtcol.
Diffstat (limited to 'src')
-rw-r--r--src/edit.rs128
-rw-r--r--src/lib.rs61
2 files changed, 141 insertions, 48 deletions
diff --git a/src/edit.rs b/src/edit.rs
index a804def..19bb486 100644
--- a/src/edit.rs
+++ b/src/edit.rs
@@ -1,6 +1,8 @@
use vtcol::{Palette, Rgb, Scheme};
-use std::{fmt, path::PathBuf, rc::Rc};
+use std::{fmt,
+ path::{Path, PathBuf},
+ rc::Rc};
use anyhow::{anyhow, Result};
@@ -161,11 +163,8 @@ slint::slint! {
GuiEdit := Window {
property scheme-name <=> name.text;
- callback set-primary ([color]);
- callback set-secondary ([color]);
-
- set-primary (colors) => { primary-colors .colors = colors; }
- set-secondary (colors) => { secondary-colors.colors = colors; }
+ property <[color]> primary <=> primary-colors .colors;
+ property <[color]> secondary <=> secondary-colors.colors;
callback get-palette-color(int) -> color;
callback set-palette-color(int, color);
@@ -476,54 +475,67 @@ impl Edit
}
});
- gui.global::<Aux>().on_handle_command_buffer(|ev, text, _pos| {
- let text = match KeyInput::from(&ev) {
- KeyInput::Printable(s) => {
- let mut text = text.to_string();
- text.push_str(&s);
- text
- },
- KeyInput::Return => {
- match Command::try_from(text.as_str()) {
- Err(e) => {
- eprintln!("bad command [{}]: {}", text, e);
- String::new()
- },
- Ok(cmd) => {
- if let Err(e) = cmd.exec() {
- eprintln!(
- "error executing command [{}]: {}",
- text, e
- );
- }
- String::new()
+ {
+ let guiw = gui.as_weak();
+ gui.global::<Aux>().on_handle_command_buffer(move |ev, text, _pos| {
+ let text = match KeyInput::from(&ev) {
+ KeyInput::Printable(s) => {
+ let mut text = text.to_string();
+ text.push_str(&s);
+ text
+ },
+ KeyInput::Return => {
+ match Command::try_from(text.as_str()) {
+ Err(e) => {
+ eprintln!("bad command [{}]: {}", text, e);
+ String::new()
+ },
+ Ok(cmd) => {
+ use slint::Model;
+ let scheme_name =
+ guiw.unwrap().get_scheme_name().to_string();
+ let prim = guiw.unwrap().get_primary();
+ let secn = guiw.unwrap().get_secondary();
+ let pal = prim.iter().chain(secn.iter())
+ .collect::<Vec<Color>>();
+ let pal = Palette::from(pal.as_slice());
+ if let Err(e) = cmd
+ .exec(scheme_name.as_str(), pal)
+ {
+ eprintln!(
+ "error executing command [{}]: {}",
+ text, e
+ );
+ }
+ String::new()
+ },
+ }
+ /* The empty string signals to leave command mode. */
+ },
+ KeyInput::Backspace =>
+ match text.char_indices().next_back() {
+ Some((i, _)) => text[..i].into(),
+ None => text.to_string(),
},
- }
- /* The empty string signals to leave command mode. */
- },
- KeyInput::Backspace =>
- match text.char_indices().next_back() {
- Some((i, _)) => text[..i].into(),
- None => text.to_string(),
+ other => {
+ eprintln!(
+ "»»» command mode input: “{}”",
+ other.to_string()
+ );
+ text.to_string()
},
- other => {
- eprintln!(
- "»»» command mode input: “{}”",
- other.to_string()
- );
- text.to_string()
- },
- };
- eprintln!("»»» command buffer: “{}”", text);
- text.into()
- });
+ };
+ eprintln!("»»» command buffer: “{}”", text);
+ text.into()
+ });
+ }
if let Some(name) = name {
gui.set_scheme_name(name.into());
}
- gui.invoke_set_primary(primary.into());
- gui.invoke_set_secondary(secondary.into());
+ gui.set_primary(primary.into());
+ gui.set_secondary(secondary.into());
gui.run();
@@ -568,5 +580,25 @@ impl TryFrom<&str> for Command
impl Command
{
- fn exec(self) -> Result<()> { todo!("got command: {:?}", self) }
+ fn exec(self, name: &str, pal: Palette) -> Result<()>
+ {
+ match self {
+ Self::Noop => Ok(()),
+ Self::Save(None) => Self::save(&PathBuf::from(&name), pal),
+ Self::Save(Some(path)) => Self::save(&path, pal),
+ }
+ //todo!("got command: {:?}", self)
+ }
+
+ fn save(path: &Path, pal: Palette) -> Result<()>
+ {
+ use std::io::Write;
+
+ let mut f =
+ std::fs::OpenOptions::new().create(true).write(true).open(path)?;
+ let pal: String = pal.into();
+ f.write_all(pal.as_bytes()).map_err(|e| {
+ anyhow!("error saving Palette to file [{}]: {}", path.display(), e)
+ })
+ }
}
diff --git a/src/lib.rs b/src/lib.rs
index 021f25a..8ecc4a6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1125,6 +1125,67 @@ impl From<&RawPalette> for Palette
}
}
+#[cfg(feature = "gui")]
+impl From<&[slint::Color]> for Palette
+{
+ fn from(colors: &[slint::Color]) -> Self
+ {
+ let mut idx: usize = 0;
+ let mut pal: [u8; PALETTE_BYTES] = [0; PALETTE_BYTES];
+
+ for &col in colors.iter() {
+ pal[idx] = col.red();
+ pal[idx + 1] = col.green();
+ pal[idx + 2] = col.blue();
+ idx += 3;
+ }
+
+ Self(pal)
+ }
+}
+
+/** Convert palette to the default text format so it can be parsed as a scheme. */
+impl Into<String> for Palette
+{
+ fn into(self) -> String
+ {
+ let mut acc = String::with_capacity(16 * 10);
+ for i in 0..PALETTE_SIZE {
+ let idx = i * 3;
+ let (r, g, b) = (self.0[idx], self.0[idx + 1], self.0[idx + 2]);
+ acc.push_str(&format!("{}#{:02.x}{:02.x}{:02.x}\n", i, r, g, b));
+ }
+ acc
+ }
+}
+
+#[test]
+fn palette_dump_as_text()
+{
+ let pal = Palette::from(&SOLARIZED_COLORS_DARK);
+ let txt = indoc::indoc! { r#"
+ 0#002b36
+ 1#dc322f
+ 2#859900
+ 3#b58900
+ 4#268bd2
+ 5#d33682
+ 6#2aa198
+ 7#eee8d5
+ 8#002b36
+ 9#cb4b16
+ 10#586e75
+ 11#657b83
+ 12#839496
+ 13#6c71c4
+ 14#93a1a1
+ 15#fdf6e3
+ "#};
+
+ let pal: String = pal.into();
+ assert_eq!(pal, txt);
+}
+
pub struct PaletteIterator
{
pal: Palette,