Skip to content

Commit

Permalink
better docs for Color.Names
Browse files Browse the repository at this point in the history
better guards around Color.Names
better color type naming
better color conversion to rgb and colorint
fixing a lot of specs
simplifying some functions as a consequence
fixing some credo issues
  • Loading branch information
a-maze-d committed Dec 1, 2023
1 parent 309b6da commit ef55ba2
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 106 deletions.
14 changes: 11 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Intro
Even though this library is published, there are things I still want to do before I consider this
as really done. Here the outstanding tasks that I can think of.
Even though this library is published, there are things I still want to do before I consider this as really done. Here the outstanding tasks that I can think of.

# Tasks
- [ ] Documentation
Expand All @@ -15,7 +14,13 @@ as really done. Here the outstanding tasks that I can think of.
- [ ] Fledex.Animation.LedAnimator
- [ ] Fledex.LedsDriver
- [ ] Add type specs (at least for the most important modules) (v0.3)
- [ ] Improve hexdocs
- [ ] Fledex
- [x] Fledex.Leds
- [x] Fledex.Color.Names
- [ ] Fledex.Animation.BaseAnimator
- [ ] Fledex.Animation.LedAnimationManager
- [ ] Fledex.Animation.LedAnimator
- [ ] Fledex.LedsDriver - [ ] Improve hexdocs
- [x] add livebooks (v0.3)
- [ ] create cheatsheet (v0.3)
- [ ] Add documentation on how to connect the LED strip to a RaspberryPi Zero (with and without level shifter).This could be part of the first example (v0.3 & v0.4)
Expand All @@ -35,6 +40,9 @@ as really done. Here the outstanding tasks that I can think of.
- [ ] see the project plan that was planned out with my son, we are not quite there yet
- [ ] Connect everything into a supervision tree (to make it more robust) (v0.4)
- [ ] Use protocols
- [ ] Drivers
- [x] Conversions `to_rgb`, `to_colorint` <-- decided against it to allow having simple structures (tuple) instead of (module)structs. Protocols don't seem to work with those.
- [ ] ??? animations & components?
- [ ] LED-component library
- [ ] Create foundation for a led-component-library that enables defining reusable led components. For example both the clock as well as the weather example have a scale it would be easy to define those as components that would make it easier to defining certain aspects (v0.5)
- [ ] Increase consumption
Expand Down
3 changes: 1 addition & 2 deletions lib/fledex/color/functions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ defmodule Fledex.Color.Functions do
|> hsv2rgb()
end

@spec create_gradient_rgb(pos_integer, Types.rgb, Types.rgb) ::
list(Types.rgb)
@spec create_gradient_rgb(pos_integer, Types.rgb, Types.rgb) :: list(Types.rgb)
def create_gradient_rgb(num_leds, {sr, sg, sb} = _start_color, {er, eg, eb} = _end_color) when num_leds > 0 do
rdist87 = (er - sr) <<< 7
gdist87 = (eg - sg) <<< 7
Expand Down
100 changes: 60 additions & 40 deletions lib/fledex/color/names.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,35 @@ defmodule Fledex.Color.Names do
"""
@external_resource Fledex.Color.LoadUtils.names_file()

import Fledex.Color.Types

alias Fledex.Color.LoadUtils
alias Fledex.Color.Types

colors = LoadUtils.load_color_file(@external_resource)

@type t :: %{
@colors colors
@color_names Enum.map(@colors, fn %{name: name} = _colorinfo -> name end)
@typedoc """
The allowed color names
"""
@type color_names_t :: unquote(
@color_names
|> Enum.map_join(" | ", &inspect/1)
|> Code.string_to_quoted!()
)
@typedoc """
The different properties that can be interrogated from a named color
"""
@type color_props_t :: (:all|:index|:name|:decriptive_name|:hex|:rgb|:hsl|:hsv|:spource)
@typedoc """
The different values that can be returned when interrogating for some named color properties
"""
@type color_vals_t :: Types.color_any() | color_struct_t | String.t
@typedoc """
The structure of a named color with all it's attributes.
"""
@type color_struct_t :: %{
index: integer,
name: atom,
name: color_names_t,
descriptive_name: String.t,
hex: Types.colorint,
rgb: Types.rgb,
Expand All @@ -36,57 +58,55 @@ defmodule Fledex.Color.Names do
source: String.t
}

colors = LoadUtils.load_color_file(@external_resource)
for color <- colors do
name = color.name
@doc """
See the module docs for `Fledex.Color.Names` for more info
"""
@doc color_name: true
@spec unquote(name)(atom) :: Types.colorint | Types.rgb | Types.hsv | Types.hsl | t
def unquote(name)(what \\ :hex)
def unquote(name)(:all), do: unquote(Macro.escape(color))
def unquote(name)(:index), do: unquote(Macro.escape(color)).index
# def unquote(name)(:name), do: unquote(Macro.escape(color)).name
def unquote(name)(:rgb), do: unquote(Macro.escape(color)).rgb
def unquote(name)(:hex), do: unquote(Macro.escape(color)).hex
def unquote(name)(:hsv), do: unquote(Macro.escape(color)).hsv
def unquote(name)(:hsl), do: unquote(Macro.escape(color)).hsl
def unquote(name)(:descriptive_name), do: unquote(Macro.escape(color)).descriptive_name
def unquote(name)(:source), do: unquote(Macro.escape(color)).source
end

@colors colors
@color_names Enum.map(@colors, fn %{name: name} = _colorinfo -> name end)

quote do
@type t :: unquote_splicing(@color_names)
end

defguard is_color_name(atom) when atom in @color_names

@doc """
Get all the data about the predefined colors
"""
@spec colors :: list(t)
@spec colors :: list(color_struct_t)
def colors do
@colors
end

@doc """
Get a list of all the predefined color (atom) names. The name can be used to either
retrieve the info by calling `info/2` or by calling the function with that
name (see also the [example livebook](3b_fledex_more_about_colors.livemd))
name (see also the __Color Names__ section nad the [example livebook](3b_fledex_more_about_colors.livemd))
"""
@spec names :: list(atom)
def names do
@color_names
end
@spec names :: list(color_names_t)
def names, do: @color_names
@doc """
Retrieve information about the color with the given name
"""
@spec info(name :: atom, what :: atom) :: Types.colorint | Types.rgb | Types.hsv | Types.hsl | t
def info(name, what \\ :hex) do
apply(__MODULE__, name, [what])
@spec info(name :: color_names_t, what :: color_props_t) :: color_vals_t
def info(name, what \\ :hex)
def info(name, what) when is_color_name(name), do: apply(__MODULE__, name, [what])
def info(_name, _what), do: nil

@base16 16
for color <- colors do
name = color.name
{r, g, b} = color.rgb
hex = color.hex
|> Integer.to_string(@base16)
|> String.pad_leading(6, "0")

@doc """
<div style="width: 25px; height: 25px; display: inline-block; background-color: ##{hex}; border: 1px solid black"></div>
Defines the color rgb(#{r}, #{g}, #{b}).
"""
@doc color_name: true
@spec unquote(name)(color_props_t) :: color_vals_t
def unquote(name)(what \\ :hex)
def unquote(name)(:all), do: unquote(Macro.escape(color))
def unquote(name)(:index), do: unquote(Macro.escape(color)).index
def unquote(name)(:name), do: unquote(Macro.escape(color)).name
def unquote(name)(:rgb), do: unquote(Macro.escape(color)).rgb
def unquote(name)(:hex), do: unquote(Macro.escape(color)).hex
def unquote(name)(:hsv), do: unquote(Macro.escape(color)).hsv
def unquote(name)(:hsl), do: unquote(Macro.escape(color)).hsl
def unquote(name)(:descriptive_name), do: unquote(Macro.escape(color)).descriptive_name
def unquote(name)(:source), do: unquote(Macro.escape(color)).source
end
end
6 changes: 4 additions & 2 deletions lib/fledex/color/types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ defmodule Fledex.Color.Types do
@type rgb :: {red :: 0..255, green :: 0..255, blue :: 0..255}
@type hsv :: {hue :: 0..255, saturation :: 0..255, value :: 0..255}
@type hsl :: {hue :: 0..255, saturation :: 0..255, light :: 0..255}
@type colorint :: 0..0xFFFFFF
@type color :: rgb | colorint | atom | Fledex.Color.Names.t
@type colorint :: 0..0xffffff

@type color_any :: color() | hsv() | hsl()
@type color :: rgb | colorint | Fledex.Color.Names.color_names_t
end
31 changes: 13 additions & 18 deletions lib/fledex/color/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ defmodule Fledex.Color.Utils do
"""
import Bitwise

require Fledex.Color.Names

alias Fledex.Color.Names
alias Fledex.Color.Types

Expand Down Expand Up @@ -107,26 +109,19 @@ defmodule Fledex.Color.Utils do
end

@doc """
This function combines the subpixels to a single (color) integer value
This function converts a color to a single (color) integer value
"""
# TODO: make more generic to accept more color types (define a protocol)
@spec to_colorint(Types.rgb) :: Types.colorint
def to_colorint({r, g, b}) do
(r<<<16) + (g<<<8) + b
end
@spec to_colorint(Types.color) :: Types.colorint
def to_colorint({r, g, b} = _color), do: (r<<<16) + (g<<<8) + b
def to_colorint(color) when is_integer(color), do: color
def to_colorint(color) when Names.is_color_name(color), do: apply(Names, color, [:hex])

@doc """
This function splits a single (color) integer value into it's rgb components
This function splits a color into it's rgb components
"""
# TODO: make more generic to accept more color types (define a protocol)
@spec to_rgb((Types.colorint | atom | Types.rgb | %{rgb: Types.rgb} | %{rgb: Types.colorint})) :: Types.rgb
def to_rgb(rgb) do
case rgb do
%{rgb: {r, g, b}} -> {r, g, b}
%{rgb: x} when is_integer(x) -> to_rgb(x)
x when is_atom(x) -> apply(Names, x, [:rgb])
x when is_integer(x) -> split_into_subpixels(x)
x -> x
end
end
@spec to_rgb((Types.color | %{rgb: Types.rgb} | %{rgb: Types.colorint})) :: Types.rgb
def to_rgb(%{rgb: x} = _color), do: to_rgb(x)
def to_rgb({r, g, b} = _color), do: {r, g, b}
def to_rgb(color) when Names.is_color_name(color), do: apply(Names, color, [:rgb])
def to_rgb(color) when is_integer(color), do: split_into_subpixels(color)
end
Loading

0 comments on commit ef55ba2

Please sign in to comment.