Class: Tuile::Sizing

Inherits:
Object
  • Object
show all
Defined in:
lib/tuile/sizing.rb

Overview

A sizing policy for a slot whose position is managed by a parent component (e.g. Component::Window#footer). Resolves one dimension at a time via #resolve, so the same value works for widths and heights.

Three policies exist:

Note that WRAP_CONTENT only makes sense for components that report a natural Component#content_size (Component::Label, Component::Button, Component::List, …). Input components (Component::TextField et al.) report Tuile::Size::ZERO, so a wrap-content slot collapses to zero width —i.e. the component becomes invisible. Use Sizing.fixed or FILL for those.

Constant Summary collapse

FILL =

Occupy everything the slot offers.

Returns:

new(mode: :fill, amount: nil)
WRAP_CONTENT =

Occupy the component’s natural Component#content_size, clamped to the slot. Components reporting Tuile::Size::ZERO collapse to invisibility — see the class doc.

Returns:

new(mode: :wrap_content, amount: nil)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#amountInteger? (readonly)

Returns the cell count for ‘:fixed`; `nil` otherwise.

Returns:

  • (Integer, nil)

    the cell count for ‘:fixed`; `nil` otherwise.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/tuile/sizing.rb', line 25

class Sizing < Data.define(:mode, :amount)
  # @param amount [Integer] the number of cells to occupy; 0 or greater.
  # @return [Sizing] a fixed-size policy.
  def self.fixed(amount)
    raise TypeError, "expected Integer, got #{amount.inspect}" unless amount.is_a?(Integer)
    raise ArgumentError, "amount must not be negative, got #{amount}" if amount.negative?

    new(mode: :fixed, amount: amount)
  end

  # Resolves one dimension of a slot.
  # @param available [Integer] cells the slot offers; 0 or greater.
  # @param content [Integer] the component's natural extent on this axis
  #   (one dimension of its {Component#content_size}).
  # @return [Integer] the resolved extent, always in `0..available`.
  def resolve(available, content)
    case mode
    when :fill then available
    when :fixed then amount.clamp(0, available)
    when :wrap_content then content.clamp(0, available)
    else raise ArgumentError, "unknown mode #{mode.inspect}"
    end
  end

  # Occupy everything the slot offers.
  # @return [Sizing]
  FILL = new(mode: :fill, amount: nil)

  # Occupy the component's natural {Component#content_size}, clamped to the
  # slot. Components reporting {Size::ZERO} collapse to invisibility — see
  # the class doc.
  # @return [Sizing]
  WRAP_CONTENT = new(mode: :wrap_content, amount: nil)
end

#modeSymbol (readonly)

Returns ‘:fill`, `:wrap_content` or `:fixed`.

Returns:

  • (Symbol)

    ‘:fill`, `:wrap_content` or `:fixed`.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/tuile/sizing.rb', line 25

class Sizing < Data.define(:mode, :amount)
  # @param amount [Integer] the number of cells to occupy; 0 or greater.
  # @return [Sizing] a fixed-size policy.
  def self.fixed(amount)
    raise TypeError, "expected Integer, got #{amount.inspect}" unless amount.is_a?(Integer)
    raise ArgumentError, "amount must not be negative, got #{amount}" if amount.negative?

    new(mode: :fixed, amount: amount)
  end

  # Resolves one dimension of a slot.
  # @param available [Integer] cells the slot offers; 0 or greater.
  # @param content [Integer] the component's natural extent on this axis
  #   (one dimension of its {Component#content_size}).
  # @return [Integer] the resolved extent, always in `0..available`.
  def resolve(available, content)
    case mode
    when :fill then available
    when :fixed then amount.clamp(0, available)
    when :wrap_content then content.clamp(0, available)
    else raise ArgumentError, "unknown mode #{mode.inspect}"
    end
  end

  # Occupy everything the slot offers.
  # @return [Sizing]
  FILL = new(mode: :fill, amount: nil)

  # Occupy the component's natural {Component#content_size}, clamped to the
  # slot. Components reporting {Size::ZERO} collapse to invisibility — see
  # the class doc.
  # @return [Sizing]
  WRAP_CONTENT = new(mode: :wrap_content, amount: nil)
end

Class Method Details

.fixed(amount) ⇒ Sizing

Returns a fixed-size policy.

Parameters:

  • amount (Integer)

    the number of cells to occupy; 0 or greater.

Returns:

  • (Sizing)

    a fixed-size policy.

Raises:

  • (TypeError)


28
29
30
31
32
33
# File 'lib/tuile/sizing.rb', line 28

def self.fixed(amount)
  raise TypeError, "expected Integer, got #{amount.inspect}" unless amount.is_a?(Integer)
  raise ArgumentError, "amount must not be negative, got #{amount}" if amount.negative?

  new(mode: :fixed, amount: amount)
end

Instance Method Details

#resolve(available, content) ⇒ Integer

Resolves one dimension of a slot.

Parameters:

  • available (Integer)

    cells the slot offers; 0 or greater.

  • content (Integer)

    the component’s natural extent on this axis (one dimension of its Component#content_size).

Returns:

  • (Integer)

    the resolved extent, always in ‘0..available`.



40
41
42
43
44
45
46
47
# File 'lib/tuile/sizing.rb', line 40

def resolve(available, content)
  case mode
  when :fill then available
  when :fixed then amount.clamp(0, available)
  when :wrap_content then content.clamp(0, available)
  else raise ArgumentError, "unknown mode #{mode.inspect}"
  end
end