1package Gtk2::Ex::FormFactory::Image;
2
3use strict;
4
5use base qw( Gtk2::Ex::FormFactory::Widget );
6
7sub get_type { "image" }
8
9sub get_with_frame		{ shift->{with_frame}			}
10sub get_bgcolor			{ shift->{bgcolor}			}
11sub get_scale_to_fit		{ shift->{scale_to_fit}			}
12sub get_max_width		{ shift->{max_width}			}
13sub get_max_height		{ shift->{max_height}			}
14sub get_widget_width		{ shift->{widget_width}			}
15sub get_widget_height		{ shift->{widget_height}		}
16sub get_scale			{ shift->{scale}			}
17sub get_scale_hook		{ shift->{scale_hook}			}
18sub get_gtk_event_box		{ shift->{gtk_event_box}		}
19
20sub set_with_frame		{ shift->{with_frame}		= $_[1]	}
21sub set_bgcolor			{ shift->{bgcolor}		= $_[1]	}
22sub set_scale_to_fit		{ shift->{scale_to_fit}		= $_[1]	}
23sub set_max_width		{ shift->{max_width}		= $_[1]	}
24sub set_max_height		{ shift->{max_height}		= $_[1]	}
25sub set_widget_width		{ shift->{widget_width}		= $_[1]	}
26sub set_widget_height		{ shift->{widget_height}	= $_[1]	}
27sub set_scale			{ shift->{scale}		= $_[1]	}
28sub set_scale_hook		{ shift->{scale_hook}		= $_[1]	}
29sub set_gtk_event_box		{ shift->{gtk_event_box}	= $_[1]	}
30
31sub get_gtk_signal_widget {
32	shift->get_gtk_event_box;
33}
34
35sub new {
36	my $class = shift;
37	my %par = @_;
38	my  ($with_frame, $bgcolor, $scale_to_fit, $max_width) =
39	@par{'with_frame','bgcolor','scale_to_fit','max_width'};
40	my  ($max_height, $scale, $scale_hook) =
41	@par{'max_height','scale','scale_hook'};
42
43	my $self = $class->SUPER::new(@_);
44
45	$scale ||= 1 unless $scale_to_fit || $scale_hook;
46
47	$self->set_with_frame($with_frame);
48	$self->set_bgcolor($bgcolor);
49	$self->set_scale_to_fit($scale_to_fit);
50	$self->set_max_width($max_width);
51	$self->set_max_height($max_height);
52	$self->set_scale($scale);
53	$self->set_scale_hook($scale_hook);
54
55	return $self;
56}
57
58sub object_to_widget {
59	my $self = shift;
60
61	my $filename   = $self->get_object_value;
62	return $self->empty_widget unless $filename and -r $filename;
63
64	my $gtk_image  = $self->get_gtk_widget;
65	my $gtk_pixbuf = Gtk2::Gdk::Pixbuf->new_from_file($filename);
66
67	my $scale_to_fit = $self->get_scale_to_fit;
68	my $max_width    = $self->get_max_width;
69	my $max_height   = $self->get_max_height;
70	my $scale        = $self->get_scale;
71	my $scale_hook   = $self->get_scale_hook;
72
73	if ( defined $scale ) {
74		my $image_width    = $gtk_pixbuf->get_width;
75		my $image_height   = $gtk_pixbuf->get_height;
76
77		if ( $scale == 1 ) {
78			$gtk_image->set_from_pixbuf ( $gtk_pixbuf );
79			$gtk_image->set_size_request ($image_width, $image_height);
80			return 1;
81		}
82
83		my $new_width  = int($image_width  * $scale);
84		my $new_height = int($image_height * $scale);
85		return if $new_width <= 0 or $new_height <= 0;
86
87		my $scaled_pixbuf = $gtk_pixbuf->scale_simple (
88			$new_width, $new_height, "GDK_INTERP_BILINEAR"
89		);
90
91		$gtk_image->set_from_pixbuf ( $scaled_pixbuf );
92		$gtk_image->set_size_request ($image_width, $image_height);
93
94	} elsif ( $scale_hook ) {
95		my $scale = &$scale_hook($self, $gtk_pixbuf);
96
97		my $image_width    = $gtk_pixbuf->get_width;
98		my $image_height   = $gtk_pixbuf->get_height;
99
100		my $new_width  = int($image_width  * $scale);
101		my $new_height = int($image_height * $scale);
102		return if $new_width <= 0 or $new_height <= 0;
103
104		my $scaled_pixbuf = $gtk_pixbuf->scale_simple (
105			$new_width, $new_height, "GDK_INTERP_BILINEAR"
106		);
107
108		$gtk_image->set_from_pixbuf ( $scaled_pixbuf );
109
110	} elsif ( $scale_to_fit or $max_width or $max_height ) {
111		my $image_width    = $gtk_pixbuf->get_width;
112		my $image_height   = $gtk_pixbuf->get_height;
113
114		my $widget_width   = $self->get_widget_width;
115		my $widget_height  = $self->get_widget_height;
116
117		$widget_width  = $max_width  if defined $max_width and
118						$max_width < $widget_width;
119		$widget_height = $max_height if defined $max_height and
120						$max_height < $widget_height;
121
122		my $width_scale  = $widget_width  / $image_width;
123		my $height_scale = $widget_height / $image_height;
124
125		my $scale = $width_scale < $height_scale ?
126			$width_scale : $height_scale;
127
128		my $new_width  = int($image_width  * $scale);
129		my $new_height = int($image_height * $scale);
130		return if $new_width <= 0 or $new_height <= 0;
131
132		my $scaled_pixbuf = $gtk_pixbuf->scale_simple (
133			$new_width, $new_height, "GDK_INTERP_BILINEAR"
134		);
135
136		$gtk_image->set_from_pixbuf ( $scaled_pixbuf );
137
138	} else {
139		$gtk_image->set_from_pixbuf ( $gtk_pixbuf );
140	}
141
142	1;
143}
144
145sub empty_widget {
146	my $self = shift;
147
148	$self->get_gtk_widget->set_from_pixbuf(undef);
149
150	1;
151}
152
1531;
154
155__END__
156
157=head1 NAME
158
159Gtk2::Ex::FormFactory::Image - An Image in a FormFactory framework
160
161=head1 SYNOPSIS
162
163  Gtk2::Ex::FormFactory::Image->new (
164    bgcolor       => Background color of the widget,
165    with_frame    => Draw a frame around the image?,
166    scale_to_fit  => Automatially scale the image in its container?,
167    max_width     => Maximum width the image may scale to,
168    max_height    => Maximum height the image may scale to,
169    scale         => Display the image with this constant scaling,
170    scale_hook    => Callback which returns the actual scale,
171    ...
172    Gtk2::Ex::FormFactory::Widget attributes
173  );
174
175=head1 DESCRIPTION
176
177This class implements an Image in a Gtk2::Ex::FormFactory framework.
178The image is always displayed with its natural aspect ratio, but
179there are various possibilities to control the scaling of the image.
180
181The value of the associated application object attribute is the
182filename of the displayed image. The file format must be supported
183by Gtk2::Gdk::PixBuf.
184
185=head1 OBJECT HIERARCHY
186
187  Gtk2::Ex::FormFactory::Intro
188
189  Gtk2::Ex::FormFactory::Widget
190  +--- Gtk2::Ex::FormFactory::Image
191
192  Gtk2::Ex::FormFactory::Layout
193  Gtk2::Ex::FormFactory::Rules
194  Gtk2::Ex::FormFactory::Context
195  Gtk2::Ex::FormFactory::Proxy
196
197=head1 ATTRIBUTES
198
199Attributes are handled through the common get_ATTR(), set_ATTR()
200style accessors, but they are mostly passed once to the object
201constructor and must not be altered after the associated FormFactory
202was built.
203
204=over 4
205
206=item B<bgcolor> = "RGB Hex Triple" [optional]
207
208This is the background color of the widget. If set all areas
209of the widget not filled with the image are painted with this
210color.
211
212=item B<with_frame> = BOOL [optional]
213
214If set to TRUE a frame is rendered around the image.
215
216=item B<scale_to_fit> = BOOL [optional]
217
218If set to TRUE the image will automatically scale proportionally
219into to the space the container of this widget allocated for the
220image widget.
221
222=item B<max_width> = INTEGER [optional]
223
224With this attribute you can define a maximm width the image may
225scale to.
226
227=item B<max_height> = INTEGER [optional]
228
229With this attribute you can define a maximm height the image may
230scale to.
231
232=item B<scale> = FLOAT [optional]
233
234If you set this attribute, no dynamic scaling applies, but the
235image will be constantly scaled with this value. This overrides
236all other attributes regarding dynamic scaling.
237
238=item B<scale_hook> = CODEREF(FormFactory::Image, PixBuf) [optional]
239
240This code reference is called if the image needs an update
241e.g. if the associated application object attribute changed or
242the parent was resized and B<scale_to_fit> was set.
243
244The Gtk2::Ex::FormFactory::Image instance and the Gtk2::Gdk::PixBuf
245of the image are passed to the function.
246
247If B<scale_to_fit> is set the widget's dimension are tracked
248automatically. The actual width and height are stored in the
249attributes B<widget_width> and B<widget_height> and thus can
250be accessed from the callback by calling B<get_widget_width>
251and B<get_widget_width>.
252
253=back
254
255For more attributes refer to L<Gtk2::Ex::FormFactory::Widget>.
256
257=head1 AUTHORS
258
259 J�rn Reder <joern at zyn dot de>
260
261=head1 COPYRIGHT AND LICENSE
262
263Copyright 2004-2006 by J�rn Reder.
264
265This library is free software; you can redistribute it and/or modify
266it under the terms of the GNU Library General Public License as
267published by the Free Software Foundation; either version 2.1 of the
268License, or (at your option) any later version.
269
270This library is distributed in the hope that it will be useful, but
271WITHOUT ANY WARRANTY; without even the implied warranty of
272MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
273Library General Public License for more details.
274
275You should have received a copy of the GNU Library General Public
276License along with this library; if not, write to the Free Software
277Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307
278USA.
279
280=cut
281