I'm (kinda') finished my library Kolorwheel.rs, it works, but I don't really like its API. Now it's a bunch of methods, which can be chained, but there're too many of them:
let kw = KolorWheel::new()
.set_count(self.cols * self.rows)
.set_hsl(self.color.h, self.color.s, self.color.l)
.hue_reli(90)
.sat_reli(-20)
.sat_offs(&self.sat_offsets[0..6])
.lit_offs(&self.lit_offsets[0..3]);
Maybe, a few simple methods would be better, which receive its command enum:
let kw = KolorWheel::new()
.init(SpinInit::SetCount(self.cols * self.rows))
.init(SpinInit::SetHsl(self.color.h, self.color.s, self.color.l))
.spin(SpinMode::HueRelativeInclusive(90))
.spin(SpinMode::SaturationRelativeInclusive(-20))
.spin(SpinMode::SaturationOffsetsSlice(&self.sat_offsets[0..6]))
.spin(SpinMode::LightnessOffsetSlice(&self.lit_offsets[0..3]));
As you see, I'm also struggling to choose a name style for the functions, e.g. change hue value relative, including specified target is now reli()
vs HueRelativeInclusive()
(and we're now not talking about case style). Maybe it's only question of taste, but all opinions are welcome.
My hint is that enum is better, but is it okay for an API, to use enum with lot of items?
The actual API is:
pub fn set_count(mut self, count: u32)
pub fn set_hsl(mut self, h: u32, s: u32, l: u32)
pub fn set_rgb(mut self, r: u8, g: u8, b: u8)
pub fn set_rgb_f(mut self, r: f32, g: f32, b: f32)
pub fn set_rgb_fa(mut self, rgb: [f32; 3])
pub fn set_rgb_hex(mut self, hex: &str)
pub fn hue_abs(mut self, amount: u32)
pub fn hue_reli(mut self, amount: i32)
pub fn hue_relx(mut self, amount: i32)
pub fn hue_vals(mut self, values: &[u32])
pub fn hue_offs(mut self, offsets: &[i32])
pub fn sat_abs(mut self, amount: u32)
pub fn sat_reli(mut self, amount: i32)
pub fn sat_relx(mut self, amount: i32)
pub fn sat_vals(mut self, values: &[u32])
pub fn sat_offs(mut self, offsets: &[i32])
pub fn lit_abs(mut self, amount: u32)
pub fn lit_reli(mut self, amount: i32)
pub fn lit_relx(mut self, amount: i32)
pub fn lit_vals(mut self, values: &[u32])
pub fn lit_offs(mut self, offsets: &[i32])
In the JavaScript version (which has a slightly less feature) I was using sentinel values to ignore H/S/L components, so the number of methods is much less, one method sets all the options, but it's not a quite readable, e.g. (warning: JS code!):
.abs(0, 0, -1, -1, 8)
Another glitch is, that absolute functions use -1 for "none", but relative functions use 0, as they can be negative as well.
I'm also struggling with return value. Now it's a primitive struct:
pub struct Color {
pub r: u8,
pub g: u8,
pub b: u8,
}
It would be great to return with egui::Color32
, but then it's not a universal lib anymore. Also, it would be great to accept egui::Color32
as parameter.
Should I write a kind of "adapter" for egui
and for other UIs as well?
Fortunately, HTML/CSS interfacing is easy, string in hex notation format does the job.
Any advice is welcome, this color thing is tripling-by-doubling my troubles (RGB x HSL), not talking about I'm pretty beginner with Rust.