# Copyright (c) 2003-2005 Ruby-GNOME2 Project Team
# This program is licenced under the same licence as Ruby-GNOME2.
#
# $Id: images.rb,v 1.5 2006/04/08 12:30:03 mutoh Exp $
=begin
= Images
Gtk::Image is used to display an image; the image can be in a number of formats.
Typically, you load an image into a GdkPixbuf::Pixbuf, then display the pixbuf.
This demo code shows some of the more obscure cases, in the simple
case a call to Gtk::Image.new is all you need.
If you want to put image data in your program as a String variable,
use the make-inline-pixbuf program that comes with GTK+.
This way you won't need to depend on loading external files, your
application binary can be self-contained.
=end
require 'common'
module Demo
class Images < BasicWindow
def initialize
@pixbuf_loader = nil
@load_timeout = 0
@image_stream = nil
super('Images')
signal_connect('destroy') do
cleanup_callback
end
self.border_width = 8
vbox = Gtk::VBox.new(false, 8)
vbox.border_width = 8
add(vbox)
label = Gtk::Label.new
label.set_markup('Image loaded from a file')
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)
# demo_find_file looks in the the current directory first,
# so you can run gtk-demo without installing GTK, then looks
# in the location where the file is installed.
pixbuf = nil
begin
filename = Demo.find_file('gtk-logo-rgb.gif')
pixbuf = GdkPixbuf::Pixbuf.new(:file => filename)
rescue
# This code shows off error handling. You can just use
# Gtk::Image.new instead if you don't want to report
# errors to the user. If the file doesn't load when using
# Gtk::Image.new, a 'missing image' icon will
# be displayed instead.
dialog = Gtk::MessageDialog.new(self,
Gtk::Dialog::DESTROY_WITH_PARENT,
Gtk::MessageDialog::ERROR,
Gtk::MessageDialog::BUTTONS_CLOSE,
"Unable to open image file 'gtk-logo-rgb.gif': #{$1}")
dialog.signal_connect('response') do |widget, data|
widget.destroy
end
dialog.show
end
image = Gtk::Image.new(pixbuf)
frame.add(image)
# Animation
label = Gtk::Label.new
label.set_markup('Animation loaded from a file')
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)
filename = Demo.find_file('floppybuddy.gif')
image = Gtk::Image.new(filename)
frame.add(image)
# Progressive
label = Gtk::Label.new
label.set_markup('Progressive image loading')
vbox.pack_start(label, false, false, 0)
frame = Gtk::Frame.new(nil)
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)
# Create an empty image for now; the progressive loader
# will create the pixbuf and fill it in.
image = Gtk::Image.new
frame.add(image)
start_progressive_loading(image)
# Sensitivity control
button = Gtk::ToggleButton.new('_Insensitive', true)
vbox.pack_start(button, false, false, 0)
button.signal_connect('toggled') do |widget|
vbox.children.each do |widget|
if widget != button
widget.sensitive = ! button.active?
end
end
end
end
def start_progressive_loading(image)
@load_timeout = Gtk.timeout_add(150) do
progressive_timeout(image)
end
end
def progressive_timeout(image)
if @image_stream
buf = @image_stream.read(256)
@pixbuf_loader.write(buf)
if @image_stream.eof?
@image_stream.close
@image_stream = nil
@pixbuf_loader.close
@pixbuf_loader = nil
end
else
filename = Demo.find_file('alphatest.png')
@image_stream = File.open(filename, 'rb')
if @pixbuf_loader != nil
@pixbuf_loader.close
@pixbuf_loader = nil
end
@pixbuf_loader = GdkPixbuf::PixbufLoader.new
@pixbuf_loader.signal_connect('area_prepared') do |loader|
pixbuf = loader.pixbuf
# Avoid displaying random memory contents, since the pixbuf
# isn't filled in yet.
pixbuf.fill!(0xaaaaaaff)
image.pixbuf = pixbuf
end
@pixbuf_loader.signal_connect('area_updated') do
# We know the pixbuf inside the Gtk::Image has changed, but the image
# itself doesn't know this; so queue a redraw. If we wanted to be
# really efficient, we could use a drawing area or something
# instead of a Gtk::Image, so we could control the exact position of
# the pixbuf on the display, then we could queue a draw for only
# the updated area of the image.
image.queue_draw
end
end
# leave timeout installed
return true
end
def cleanup_callback
@pixbuf_loader.close if @pixbuf_loader
@pixbuf_loader = nil
if @load_timeout != 0
Gtk.timeout_remove(@load_timeout)
end
end
end
end