Module: Clogs::Style

Defined in:
lib/clogs/style.rb

Overview

Coercion of Shoes style values into the numbers and colours the painter wants. Shoes is famously relaxed about types: a width can be 100, 0.5, "50%" or -20, and a colour can be a symbol, a string, an array or a Shoes::Color.

Class Method Summary collapse

Class Method Details

.channel(value) ⇒ Object

One colour channel, from either convention.



65
66
67
68
69
70
# File 'lib/clogs/style.rb', line 65

def channel(value)
  return 0 if value.nil?
  return (value.clamp(0.0, 1.0) * 255).round if value.is_a?(Float) && value <= 1.0

  value.to_i.clamp(0, 255)
end

.color(value, default = nil) ⇒ Object

Shoes colours reach the display service as [r, g, b, a] arrays, but user code can also set a bare symbol or "#ff0000" that never went through Shoes::Colors.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/clogs/style.rb', line 39

def color(value, default = nil)
  case value
  when nil then default
  when Array
    # Shoes accepts both 0-255 integers and 0.0-1.0 floats, and mixes them
    # freely: `black(0.6)` is [0, 0, 0, 0.6].
    r, g, b, a = value
    [channel(r), channel(g), channel(b), a.nil? ? 255 : channel(a)]
  when String
    if value.start_with?("#")
      hex(value)
    else
      named(value) || default
    end
  when Symbol
    named(value.to_s) || default
  else
    if value.respond_to?(:to_a)
      color(value.to_a, default)
    else
      default
    end
  end
end

.dimension(value, available) ⇒ Object

Resolve a Shoes dimension against the space available.

100    => 100 pixels
0.5    => half of `available`
"50%"  => half of `available`
-20    => `available` minus 20
nil    => nil (meaning "size yourself")


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/clogs/style.rb', line 18

def dimension(value, available)
  case value
  when nil then nil
  when Integer
    value.negative? ? [available + value, 0].max : value
  when Float
    value <= 1.0 && value >= -1.0 ? (available * value).round : value.round
  when String
    if value.end_with?("%")
      (available * value.to_f / 100.0).round
    else
      value.to_i
    end
  else
    value.respond_to?(:to_i) ? value.to_i : nil
  end
end

.hex(str) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/clogs/style.rb', line 72

def hex(str)
  s = str.delete_prefix("#")
  s = s.chars.map { |c| c * 2 }.join if s.length == 3
  alpha = s[6, 2]
  [s[0, 2].to_i(16), s[2, 2].to_i(16), s[4, 2].to_i(16),
   alpha.nil? || alpha.empty? ? 255 : alpha.to_i(16)]
end

.margins(styles) ⇒ Object

Shoes lets a margin be one number or [left, top, right, bottom].



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/clogs/style.rb', line 89

def margins(styles)
  m = styles["margin"] || styles[:margin]
  base = case m
  when nil then [0, 0, 0, 0]
  when Array then m.map(&:to_i)
  when Numeric then [m.to_i] * 4
  when String then [m.to_i] * 4
  else [0, 0, 0, 0]
  end
  left, top, right, bottom = base
  [
    (styles["margin_left"] || left).to_i,
    (styles["margin_top"] || top).to_i,
    (styles["margin_right"] || right).to_i,
    (styles["margin_bottom"] || bottom).to_i
  ]
end

.named(name) ⇒ Object



80
81
82
83
84
85
86
# File 'lib/clogs/style.rb', line 80

def named(name)
  require "shoes/colors" if !defined?(Shoes::Colors)
  rgb = Shoes::Colors.to_rgb(name.to_sym)
  rgb.is_a?(Array) ? color(rgb) : nil
rescue StandardError
  nil
end

.paddings(styles) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/clogs/style.rb', line 107

def paddings(styles)
  p = styles["padding"] || styles[:padding]
  base = case p
  when nil then [0, 0, 0, 0]
  when Array then p.map(&:to_i)
  when Numeric then [p.to_i] * 4
  else [0, 0, 0, 0]
  end
  left, top, right, bottom = base
  [
    (styles["padding_left"] || left).to_i,
    (styles["padding_top"] || top).to_i,
    (styles["padding_right"] || right).to_i,
    (styles["padding_bottom"] || bottom).to_i
  ]
end