lib/vedeu/geometries/area/area.rb
# frozen_string_literal: true
module Vedeu
module Geometries
# Define an area from dimensions or points.
#
# @api private
#
class Area
extend Forwardable
def_delegators :border,
:bottom?,
:enabled?,
:left?,
:right?,
:top?
# @!attribute [r] y
# @return [Fixnum] Returns the top coordinate (row/line start
# position) of the interface.
attr_reader :y
alias top y
# @!attribute [r] yn
# @return [Fixnum] Returns the bottom coordinate (row/line end
# position) of the interface.
attr_reader :yn
alias bottom yn
# @!attribute [r] x
# @return [Fixnum] Returns the left coordinate (column/character
# start position) of the interface.
attr_reader :x
alias left x
# @!attribute [r] xn
# @return [Fixnum] Returns the right coordinate (column/
# character end position) of the interface.
attr_reader :xn
alias right xn
# @param attributes [Hash<Symbol => Boolean|Fixnum|Symbol>]
# @option attributes horizontal_alignment [Symbol]
# @option attributes maximised [Boolean]
# @option attributes name [String|Symbol]
# @option attributes vertical_alignment [Symbol]
# @option attributes x [Fixnum] The starting x coordinate.
# @option attributes xn [Fixnum] The ending x coordinate.
# @option attributes width [Fixnum]
# @option attributes y [Fixnum] The starting y coordinate.
# @option attributes yn [Fixnum] The ending y coordinate.
# @option attributes height [Fixnum]
# @return [Vedeu::Geometries::Area]
def self.from_attributes(attributes = {})
y_attributes = {
alignment: attributes[:vertical_alignment],
d: attributes[:y],
dn: attributes[:yn],
d_dn: attributes[:height],
maximised: attributes[:maximised],
}
x_attributes = {
alignment: attributes[:horizontal_alignment],
d: attributes[:x],
dn: attributes[:xn],
d_dn: attributes[:width],
maximised: attributes[:maximised],
}
dy, dyn = Vedeu::Geometries::YDimension.pair(y_attributes)
dx, dxn = Vedeu::Geometries::XDimension.pair(x_attributes)
new(name: attributes[:name],
y: dy,
yn: dyn,
x: dx,
xn: dxn)
end
# Returns a new instance of Vedeu::Area.
#
# @macro param_name
# @param y [Fixnum] The starting row/line position.
# @param yn [Fixnum] The ending row/line position.
# @param x [Fixnum] The starting column/character position.
# @param xn [Fixnum] The ending column/character position.
# @return [Vedeu::Geometries::Area]
def initialize(name:, y:, yn:, x:, xn:)
@name = name
@y = y
@yn = yn
@x = x
@xn = xn
end
# An object is equal when its values are the same.
#
# @param other [Vedeu::Geometries::Area]
# @return [Boolean]
def eql?(other)
self.class.equal?(other.class) &&
name == other.name &&
y == other.y &&
yn == other.yn &&
x == other.x &&
xn == other.xn
end
alias == eql?
# Returns the width of the interface determined by whether a
# left, right, both or neither borders are shown.
#
# @return [Fixnum]
def bordered_width
return width unless border && enabled?
if left? && right?
width - 2
elsif left? || right?
width - 1
else
width
end
end
# Returns the height of the interface determined by whether a
# top, bottom, both or neither borders are shown.
#
# @return [Fixnum]
def bordered_height
return height unless border && enabled?
if top? && bottom?
height - 2
elsif top? || bottom?
height - 1
else
height
end
end
# Return the column position for 1 character right of the left
# border.
#
# @return [Fixnum]
def bx
(enabled? && left?) ? x + 1 : x
end
# Return the column position for 1 character left of the right
# border.
#
# @return [Fixnum]
def bxn
(enabled? && right?) ? xn - 1 : xn
end
# Return the row position for 1 character under of the top
# border.
#
# @return [Fixnum]
def by
(enabled? && top?) ? y + 1 : y
end
# Return the column position for 1 character above of the bottom
# border.
#
# @return [Fixnum]
def byn
(enabled? && bottom?) ? yn - 1 : yn
end
# Returns an array containing the centred y and x coordinates of
# the interface.
#
# @return [Array<Fixnum>]
def centre
[centre_y, centre_x]
end
# Returns the centred y coordinate (the vertical centre row) of
# the interface.
#
# @return [Fixnum]
def centre_y
(height / 2) + y
end
# Returns the centred x coordinate (the horizontal centre
# character) of the interface.
#
# @return [Fixnum]
def centre_x
(width / 2) + x
end
# Returns the height of the interface.
#
# @return [Fixnum]
def height
(yn - y) + 1
end
# Returns the width of the interface.
#
# @return [Fixnum]
def width
(xn - x) + 1
end
# Returns the row above the top by default.
#
# @example
# `top` or `y` is 4.
#
# north # => 3
# north(2) # => 2 (positive goes 'more' north)
# north(-4) # => 8 (negative goes south)
#
# @param offset [Fixnum]
# @return [Fixnum]
def north(offset = 1)
y - offset
end
# Returns the column after right by default.
#
# @example
# `right` or `xn` is 19.
#
# east # => 20
# east(2) # => 21 (positive goes 'more' east)
# east(-4) # => 15 (negative goes west)
#
# @param offset [Fixnum]
# @return [Fixnum]
def east(offset = 1)
xn + offset
end
# Returns the row below the bottom by default.
#
# @example
# `bottom` or `yn` is 12.
#
# south # => 13
# south(2) # => 14 (positive goes 'more' south)
# south(-4) # => 8 (negative goes north)
#
# @param offset [Fixnum]
# @return [Fixnum]
def south(offset = 1)
yn + offset
end
# Returns the column before left by default.
#
# @example
# `left` or `x` is 8.
#
# west # => 7
# west(2) # => 6 (positive goes 'more' west)
# west(-4) # => 12 (negative goes east)
#
# @param offset [Fixnum]
# @return [Fixnum]
def west(offset = 1)
x - offset
end
protected
# @!attribute [r] name
# @macro return_name
attr_reader :name
private
# @macro border_by_name
def border
@_border ||= Vedeu.borders.by_name(name)
end
end # Area
end # Geometries
end # Vedeu