#!/usr/bin/ruby

# This program displays a pixel-based animation in a window

# FIXME: Update the picture 20 times per second

require 'gtk2'

class BasicWindow < Gtk::Window
  def initialize(title = nil)
    super(Gtk::Window::TOPLEVEL)
    if title
      set_title("#{title} in Ruby/GTK")
    end

    signal_connect("key_press_event") do |widget, event|
      if event.state.control_mask? and event.keyval == Gdk::Keyval::GDK_q
        destroy
        true
      else
        false
      end
    end

    signal_connect("delete_event") do |widget, event|
      quit
    end
  end

  def quit
    destroy
    true
  end
end

class Image < BasicWindow
  # Create a string of 100x100x4 characters
  def pixels
    result = ""

    @offset = 0 unless defined? @offset
    100.times do |y|
      100.times do |x|
        # Red component
        result << (((x + @offset) * 255) / (100 + @offset))

        # Green component
        result << (((y + @offset) * 255) / (100 + @offset))

        # Blue component
        result << 128

        # Padding
        result << 0
      end
    end
    @offset += 1

    return result
  end

  def initialize
    super('Image')
    signal_connect('destroy') do
      Gtk.main_quit
    end

    self.border_width = 8

    vbox = Gtk::VBox.new(false, 8)
    vbox.border_width = 8
    add(vbox)

    label = Gtk::Label.new
    label.set_markup('<u>Rendered image</u>')
    vbox.pack_start(label, false, false, 0)

    frame = Gtk::Frame.new
    frame.shadow_type = Gtk::SHADOW_IN

    # The alignment keeps the frame from growing when users resize
    # the window
    align = Gtk::Alignment.new(0.5, 0.5, 0, 0)
    align.add(frame)
    vbox.pack_start(align, false, false, 0)

    # Realize the window to be able to properly do graphics operations
    realize

    pixmap = Gdk::Pixmap.new(window, 100, 100, -1)
    image = Gtk::Image.new(pixmap)
    frame.add(image)

    image.realize

    Gtk.timeout_add(50) do
      gc = Gdk::GC.new(image.window)
      Gdk::RGB.draw_rgb_32_image(pixmap, gc, 0, 0, 100, 100, Gdk::RGB::DITHER_NONE, pixels, 100*4)
      true
    end
  end
end

# Do the Disco Duck
image = Image.new
image.show_all
Gtk.main
