summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2022-08-07 11:55:44 +0200
committerPhilipp Gesang <phg@phi-gamma.net>2022-08-08 23:10:37 +0200
commitadc525cf75a08eef7aa96c7ca56eef5617becc06 (patch)
treeaa492e94a746605f7eab342bd27e2d915cdbb760
parent48342e5bc46380d977edf178e31ad518eac7bd20 (diff)
downloadvtcol-adc525cf75a08eef7aa96c7ca56eef5617becc06.tar.gz
edit: present color palette
No actual editing functionality yet, just the colors layed out as squares on an 8?2 grid.
-rw-r--r--src/edit.rs184
-rw-r--r--src/lib.rs50
-rw-r--r--src/vtcol.rs4
3 files changed, 235 insertions, 3 deletions
diff --git a/src/edit.rs b/src/edit.rs
new file mode 100644
index 0000000..a166ce4
--- /dev/null
+++ b/src/edit.rs
@@ -0,0 +1,184 @@
+use vtcol::{Palette, Rgb, Scheme};
+
+use std::rc::Rc;
+
+use anyhow::{anyhow, Result};
+
+use slint::{Color, VecModel};
+
+slint::slint! {
+ import { HorizontalBox, VerticalBox } from "std-widgets.slint";
+
+ export global Aux := {
+ callback format-rgb-hex(color) -> string;
+ }
+
+ GuiEdit := Window {
+ property scheme-name <=> name.text;
+
+ property <[color]> primary: [
+ rgb( 0, 0, 0),
+ ];
+
+ property <[color]> secondary: [
+ rgb(255, 255, 255),
+ ];
+
+ VerticalBox {
+ alignment: start;
+
+ status := HorizontalBox {
+ width : 100%;
+
+ name := Text {
+ text : "<unnamed>";
+ color : #a0a0a0;
+ font-weight : 700;
+ }
+ }
+
+ primary-colors := Rectangle {
+ width : 100%;
+ background : #aaaaaa;
+ border-width : 2px;
+
+ squares-primary := HorizontalBox {
+ width : 100%;
+ height : 20px;
+
+ for col[i] in primary : psquare := Rectangle {
+ property <color> current-color : col;
+ width : 86px;
+ height : 86px;
+ border-color : ptouch.has-hover ? #eeeeee : #333333;
+ border-width : 3px;
+
+ ptouch := TouchArea {
+ }
+
+ prect := Rectangle {
+ y : 3px;
+ x : 3px;
+ width : 80px;
+ height : 80px;
+ background : current-color;
+
+ VerticalBox {
+ pdesc := Text {
+ text : i;
+ }
+ Rectangle {
+ background : ptouch.has-hover ? #ffffff77 : #cccccc33;
+ pval := Text {
+ text : Aux.format-rgb-hex(current-color);
+ font-size : 9pt;
+ }
+ }
+ Rectangle { }
+ }
+ }
+ }
+ }
+ }
+
+ secondary-colors := Rectangle {
+ width : 100%;
+ background : #bbbbbb;
+ border-width : 2px;
+
+ squares-secondary := HorizontalBox {
+ width : 100%;
+ height : 20px;
+
+ for col[i] in secondary : ssquare := Rectangle {
+ property <color> current-color : col;
+ property <int> i2 : i + 8;
+ width : 86px;
+ height : 86px;
+ border-color : stouch.has-hover ? #eeeeee : #333333;
+ border-width : 3px;
+
+ stouch := TouchArea {
+ }
+
+ srect := Rectangle {
+ y : 3px;
+ x : 3px;
+ width : 80px;
+ height : 80px;
+ background : current-color;
+
+ VerticalBox {
+ sdesc := Text {
+ text : i;
+ }
+ Rectangle {
+ background : stouch.has-hover ? #ffffff77 : #cccccc33;
+ sval := Text {
+ text : Aux.format-rgb-hex(current-color);
+ font-size : 9pt;
+ }
+ }
+ Rectangle { }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+pub struct Edit
+{
+ name: Option<String>,
+ scheme: Scheme,
+}
+
+impl Edit
+{
+ pub fn new(name: Option<String>, scheme: Scheme) -> Self
+ {
+ Self { name, scheme }
+ }
+
+ pub fn run(self) -> Result<()>
+ {
+ let Self { name, scheme } = self;
+
+ let pal = Palette::try_from(&scheme)?.iter().collect::<Vec<Rgb>>();
+
+ let primary = pal[0..8]
+ .iter()
+ .map(|Rgb(r, g, b)| Color::from_rgb_u8(*r, *g, *b))
+ .collect::<Vec<Color>>();
+
+ let secondary = pal[8..]
+ .iter()
+ .map(|Rgb(r, g, b)| Color::from_rgb_u8(*r, *g, *b))
+ .collect::<Vec<Color>>();
+
+ let primary = Rc::new(VecModel::from(primary));
+ let secondary = Rc::new(VecModel::from(secondary));
+
+ let gui = GuiEdit::new();
+
+ gui.global::<Aux>().on_format_rgb_hex(|col| {
+ let x = (col.red() as u32) << 2
+ | (col.green() as u32) << 1
+ | (col.blue() as u32);
+ format!("#{:06x}", x).into()
+ });
+
+ if let Some(name) = name {
+ gui.set_scheme_name(name.into());
+ }
+
+ gui.set_primary(primary.into());
+ gui.set_secondary(secondary.into());
+
+ gui.run();
+
+ Ok(())
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 5032f68..021f25a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -846,14 +846,17 @@ macro_rules! byte_of_hex {
};
}
-struct Rgb(u8, u8, u8);
+pub struct Rgb(pub u8, pub u8, pub u8);
impl Rgb
{
+ #[inline]
fn r(&self) -> u8 { self.0 }
+ #[inline]
fn g(&self) -> u8 { self.1 }
+ #[inline]
fn b(&self) -> u8 { self.2 }
}
@@ -871,6 +874,18 @@ impl TryFrom<&[u8; 6]> for Rgb
}
}
+impl From<[u8; 3]> for Rgb
+{
+ fn from(bytes: [u8; 3]) -> Self
+ {
+ let r = bytes[0];
+ let g = bytes[1];
+ let b = bytes[2];
+
+ Self(r, g, b)
+ }
+}
+
impl From<u32> for Rgb
{
fn from(rgb: u32) -> Self
@@ -1028,6 +1043,7 @@ impl Palette
Ok(res)
}
+ pub fn iter(&self) -> PaletteIterator { PaletteIterator::new(&self) }
/* [Palette::from_stdin] */
} /* [impl Palette] */
@@ -1109,6 +1125,38 @@ impl From<&RawPalette> for Palette
}
}
+pub struct PaletteIterator
+{
+ pal: Palette,
+ cur: usize,
+}
+
+impl PaletteIterator
+{
+ fn new(pal: &Palette) -> Self { Self { pal: pal.clone(), cur: 0 } }
+}
+
+impl Iterator for PaletteIterator
+{
+ type Item = Rgb;
+
+ fn next(&mut self) -> Option<Self::Item>
+ {
+ if self.cur >= PALETTE_SIZE {
+ None
+ } else {
+ let off = self.cur * 3;
+ let rgb = Rgb::from([
+ self.pal.0[off],
+ self.pal.0[off + 1],
+ self.pal.0[off + 2],
+ ]);
+ self.cur += 1;
+ Some(rgb)
+ }
+ }
+}
+
const CONSOLE_PATHS: [&str; 6] = [
"/proc/self/fd/0",
"/dev/tty",
diff --git a/src/vtcol.rs b/src/vtcol.rs
index f12af09..feb8f0b 100644
--- a/src/vtcol.rs
+++ b/src/vtcol.rs
@@ -330,9 +330,9 @@ impl ColorJob
fn edit(name: Option<String>, scm: Scheme) -> Result<()>
{
vrb!("Launching color scheme editor for scheme {}", scm);
- let editor = crate::edit::Edit::new();
+ let editor = crate::edit::Edit::new(name, scm);
- editor.run(name, scm)
+ editor.run()
}
#[cfg(not(feature = "gui"))]