<commit_before>if Kernel.respond_to?(:require)
  require 'cura/attributes/has_initialize'
  require 'cura/attributes/has_application'
  require 'cura/attributes/has_focusability'
  require 'cura/attributes/has_colors'
  require 'cura/attributes/has_dimensions'
  require 'cura/attributes/has_events'
  require 'cura/attributes/has_offsets'
  require 'cura/attributes/has_relative_coordinates'
end

module Cura
  module Component
    
    # The base class for all components.
    #
    # All components use a box model similar to CSS.
    # Margins, borders, paddings, then content.
    class Base
      
      include Attributes::HasInitialize
      include Attributes::HasDimensions
      include Attributes::HasEvents
      include Attributes::HasFocusability
      include Attributes::HasColors
      include Attributes::HasOffsets
      include Attributes::HasRelativeCoordinates
      
      # Get the outer width of this component.
      # This is the dimension including any borders, margins, or padding sizes.
      #
      # @return [Integer]
      def outer_width # TODO: Remove
        width + offsets.width + padding.width
      end
      
      # Get the outer width of this component.
      # This is the dimension including any borders, margins, or padding sizes.
      #
      # @return [Integer]
      def outer_height # TODO: Remove
        height + offsets.height + padding.height
      end
      
      # Get the cursor for this application.
      # TODO: Delegate
      #
      # @return [Cursor]
      def cursor
        application.cursor
      end
      
      # Get the pencil for this application.
      # TODO: Delegate
      #
      # @return [Pencil]
      def pencil
        application.pencil
      end
      
      # Update this component.
      #
      # @return [Component]
      def update
        self
      end
      
      # Draw this component.
      #
      # @return [Component]
      def draw
        draw_background
        draw_border
        
        self
      end
      
      # Get the application of this object.
      #
      # @return [Application]
      def application
        return nil if parent.nil?
        
        parent.application
      end
      
      # Focus on this component.
      #
      # @return [nil, Component] This component or nil if it isn't focusable.
      def focus
        return nil unless @focusable
        
        application.focus(self)
      end
      
      # Check whether this component is focused.
      #
      # @return [Boolean]
      def focused?
        application.focused == self # TODO: application.focused?(self)
      end
      
      # Translate absolute coordinates to relative coordinates.
      #
      # @param [#to_hash, #to_h] options
      # @option options [#to_i] :x
      # @option options [#to_i] :y
      # @return [Hash] The new coordinates.
      def translate(options={})
        options = options.to_hash rescue options.to_h
        
        {
          x: absolute_x + options[:x].to_i,
          y: absolute_y + options[:y].to_i
        }
      end
      
      # Instance inspection.
      #
      # @return [String]
      def inspect
        "#<#{self.class}:0x#{__id__.to_s(16)} x=#{x} y=#{y} absolute_x=#{absolute_x} absolute_y=#{absolute_y} w=#{width} h=#{height} parent=#{@parent.class}:0x#{@parent.__id__.to_s(16)}>"
      end
      
      protected
      
      # Draw the background of this component.
      def draw_background
        options = translate( x: @offsets.left, y: @offsets.top ).merge( width: width + @padding.width, height: height + @padding.height, foreground: foreground, background: background )
        
        pencil.draw_rectangle( options )
      end
      
      # Draw the border of this component.
      def draw_border # TODO
        if border.top > 0 # TODO: :none
          options = translate( x: margin.left, y: margin.top ).merge( width: width + margin.width, height: border.top, foreground: border.foreground, background: Color.red )
          
          pencil.draw_rectangle( options )
        end
        
        if border.bottom > 0 # TODO: :none
          options = translate( x: margin.left, y: offsets.top + padding.bottom ).merge( width: width + margin.width, height: border.bottom, foreground: border.foreground, background: Color.red )
          
          pencil.draw_rectangle( options )
        end
      end
      
      def switch_colors
        f, b = foreground, background
        
        self.foreground, self.background = b, f
      end
      
    end
    
  end
end<commit_msg>Color inheriting is now on Component::Base<commit_after>if Kernel.respond_to?(:require)
  require 'cura/attributes/has_initialize'
  require 'cura/attributes/has_application'
  require 'cura/attributes/has_focusability'
  require 'cura/attributes/has_colors'
  require 'cura/attributes/has_dimensions'
  require 'cura/attributes/has_events'
  require 'cura/attributes/has_offsets'
  require 'cura/attributes/has_relative_coordinates'
end

module Cura
  module Component
    
    # The base class for all components.
    #
    # All components use a box model similar to CSS.
    # Margins, borders, paddings, then content.
    class Base
      
      include Attributes::HasInitialize
      include Attributes::HasDimensions
      include Attributes::HasEvents
      include Attributes::HasFocusability
      include Attributes::HasColors
      include Attributes::HasOffsets
      include Attributes::HasRelativeCoordinates
      
      # Get the outer width of this component.
      # This is the dimension including any borders, margins, or padding sizes.
      #
      # @return [Integer]
      def outer_width # TODO: Remove
        width + offsets.width + padding.width
      end
      
      # Get the outer width of this component.
      # This is the dimension including any borders, margins, or padding sizes.
      #
      # @return [Integer]
      def outer_height # TODO: Remove
        height + offsets.height + padding.height
      end
      
      # Get the cursor for this application.
      # TODO: Delegate
      #
      # @return [Cursor]
      def cursor
        application.cursor
      end
      
      # Get the pencil for this application.
      # TODO: Delegate
      #
      # @return [Pencil]
      def pencil
        application.pencil
      end
      
      # Update this component.
      #
      # @return [Component]
      def update
        self
      end
      
      # Draw this component.
      #
      # @return [Component]
      def draw
        draw_background
        draw_border
        
        self
      end
      
      # Get the application of this object.
      #
      # @return [Application]
      def application
        return nil if parent.nil?
        
        parent.application
      end
      
      # Focus on this component.
      #
      # @return [nil, Component] This component or nil if it isn't focusable.
      def focus
        return nil unless @focusable
        
        application.focus(self)
      end
      
      # Check whether this component is focused.
      #
      # @return [Boolean]
      def focused?
        application.focused == self # TODO: application.focused?(self)
      end
      
      # Translate absolute coordinates to relative coordinates.
      #
      # @param [#to_hash, #to_h] options
      # @option options [#to_i] :x
      # @option options [#to_i] :y
      # @return [Hash] The new coordinates.
      def translate(options={})
        options = options.to_hash rescue options.to_h
        
        {
          x: absolute_x + options[:x].to_i,
          y: absolute_y + options[:y].to_i
        }
      end
      
      # Get the foreground color of this object.
      #
      # @return [Color]
      def foreground
        get_or_inherit_color( :foreground, Color.black )
      end
      
      # Get the background color of this object.
      #
      # @return [Color]
      def background
        get_or_inherit_color( :background, Color.white )
      end
      
      # Instance inspection.
      #
      # @return [String]
      def inspect
        "#<#{self.class}:0x#{__id__.to_s(16)} x=#{x} y=#{y} absolute_x=#{absolute_x} absolute_y=#{absolute_y} w=#{width} h=#{height} parent=#{@parent.class}:0x#{@parent.__id__.to_s(16)}>"
      end
      
      protected
      
      # Draw the background of this component.
      def draw_background
        options = translate( x: @offsets.left, y: @offsets.top ).merge( width: width + @padding.width, height: height + @padding.height, foreground: foreground, background: background )
        
        pencil.draw_rectangle( options )
      end
      
      # Draw the border of this component.
      def draw_border # TODO
        if border.top > 0 # TODO: :none
          options = translate( x: margin.left, y: margin.top ).merge( width: width + margin.width, height: border.top, foreground: border.foreground, background: Color.red )
          
          pencil.draw_rectangle( options )
        end
        
        if border.bottom > 0 # TODO: :none
          options = translate( x: margin.left, y: offsets.top + padding.bottom ).merge( width: width + margin.width, height: border.bottom, foreground: border.foreground, background: Color.red )
          
          pencil.draw_rectangle( options )
        end
      end
      
      def switch_colors
        f, b = foreground, background
        
        self.foreground, self.background = b, f
      end
      
      def get_or_inherit_color(name, default)
        value = instance_variable_get("@#{name}")
        
        return value unless value == :inherit
        return default unless respond_to?(:parent) && parent.respond_to?(name)
        
        parent.send(name)
      end
      
    end
    
  end
end
{'fraction_non_alphanumeric': 0.0854368932038835, 'fraction_numerical': 0.0016351558507920285, 'mean_word_length': 1.993576017130621, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5186236', 'n_tokens_mistral': 2740, 'n_tokens_neox': 2706, 'n_words': 791}