class Magick::Image::View::Rows

Magick::Image::View::Rows

def [](*args)

def [](*args)
  cols(args)
  # Both View::Pixels and Magick::Pixel implement Observable
  if @unique
    pixels = @view[@rows[0] * @width + @cols[0]]
    pixels.add_observer(self)
  else
    pixels = View::Pixels.new
    each do |x|
      p = @view[x]
      p.add_observer(self)
      pixels << p
    end
  end
  pixels
end

def []=(*args)

def []=(*args)
  rv = args.delete_at(-1) # get rvalue
  unless rv.is_a?(Pixel) # must be a Pixel or a color name
    begin
      rv = Pixel.from_color(rv)
    rescue TypeError
      Kernel.raise TypeError, "cannot convert #{rv.class} into Pixel"
    end
  end
  cols(args)
  each { |x| @view[x] = rv.dup }
  changed
  notify_observers(self)
end

def cols(*args)

def cols(*args)
  @cols = args[0] # remove the outermost array
  @unique = false
  # Convert @rows to an Enumerable object
  case @rows.length
  when 0                      # Create a Range for all the rows
    @rows = Range.new(0, @height, true)
  when 1                      # Range, Array, or a single integer
    # if the single element is already an Enumerable
    # object, get it.
    if @rows.first.respond_to? :each
      @rows = @rows.first
    else
      @rows = Integer(@rows.first)
      @rows += @height if @rows < 0
      Kernel.raise IndexError, "index [#{@rows}] out of range" if @rows < 0 || @rows > @height - 1
      # Convert back to an array
      @rows = Array.new(1, @rows)
      @unique = true
    end
  when 2
    # A pair of integers representing the starting column and the number of columns
    start = Integer(@rows[0])
    length = Integer(@rows[1])
    # Negative start -> start from last row
    start += @height if start < 0
    if start > @height || start < 0 || length < 0
      Kernel.raise IndexError, "index [#{@rows.first}] out of range"
    elsif start + length > @height
      length = @height - length
      length = [length, 0].max
    end
    # Create a Range for the specified set of rows
    @rows = Range.new(start, start + length, true)
  end
  case @cols.length
  when 0 # all rows
    @cols = Range.new(0, @width, true) # convert to range
    @unique = false
  when 1 # Range, Array, or a single integer
    # if the single element is already an Enumerable
    # object, get it.
    if @cols.first.respond_to? :each
      @cols = @cols.first
      @unique = false
    else
      @cols = Integer(@cols.first)
      @cols += @width if @cols < 0
      Kernel.raise IndexError, "index [#{@cols}] out of range" if @cols < 0 || @cols > @width - 1
      # Convert back to array
      @cols = Array.new(1, @cols)
      @unique &&= true
    end
  when 2
    # A pair of integers representing the starting column and the number of columns
    start = Integer(@cols[0])
    length = Integer(@cols[1])
    # Negative start -> start from last row
    start += @width if start < 0
    if start > @width || start < 0 || length < 0
    # nop
    elsif start + length > @width
      length = @width - length
      length = [length, 0].max
    end
    # Create a Range for the specified set of columns
    @cols = Range.new(start, start + length, true)
    @unique = false
  end
end

def each

iterator called from subscript methods
def each
  maxrows = @height - 1
  maxcols = @width - 1
  @rows.each do |j|
    Kernel.raise IndexError, "index [#{j}] out of range" if j > maxrows
    @cols.each do |i|
      Kernel.raise IndexError, "index [#{i}] out of range" if i > maxcols
      yield j * @width + i
    end
  end
  nil # useless return value
end

def initialize(view, width, height, rows)

def initialize(view, width, height, rows)
  @view = view
  @width = width
  @height = height
  @rows = rows
end

def update(pixel)

A pixel has been modified. Tell the view.
def update(pixel)
  changed
  notify_observers(self)
  pixel.delete_observer(self) # Don't need to hear again.
  nil
end