Re: image layout questions
- From: zentara <zentara1 sbcglobal net>
- To: gtk-perl-list gnome org
- Subject: Re: image layout questions
- Date: Tue, 7 Aug 2007 07:03:35 -0400
On Tue, 7 Aug 2007 19:03:04 +1200
"Johan Aberg" <abergster gmail com> wrote:
I'm looking for a way to display images in a horizontal layout. I'm
building a timeline displaying images from left to right. I'd like to
be able to use set_reorderable(TRUE) to shuffle the images around left
or right on this timeline.
The TreeView seems to be a good candidate of doing this, but it seems
to be design to show data in rows and columns in a vertical layout. I
only want one row with lots of columns and I need to be able to access
each cell to reorder them.
Any suggestion what widget/class that could help me out here?
I wrote this thumbnail-previwer awhile ago. It uses the Gnome2::Canvas
for display. I display the thumbnails vertically, but you could
easily switch it to horizontal. Reordering them out to be easy too.
Anyways, just run the script in a directory
full of images.... it will find all images and recurse into sub-dirs.
As far as widgets go, for doing specialized things of your imagination,
it's hard to beat a Canvas.
#!/usr/bin/perl
use warnings;
use strict;
use Gtk2 '-init';
use Glib qw/TRUE FALSE/;
use Gnome2::Canvas;
chdir '..'; #little hack to load any images in toplevel directory
#otherwise only subdirs are shown at opening
#automatically put full file path to clipboards
#to paste menu
my $clipboard = Gtk2::Clipboard->get(Gtk2::Gdk->SELECTION_CLIPBOARD);
#to mouse
my $clipboard1 = Gtk2::Clipboard->get(Gtk2::Gdk->SELECTION_PRIMARY);
my $window = Gtk2::Window->new('toplevel');
$window->signal_connect('delete_event' => sub { Gtk2->main_quit; });
$window->set_border_width(5);
$window->set_default_size(600,400);
my $vbox = Gtk2::VBox->new(0,1);
#create a hbox to pack the information label
my $hbox0 = Gtk2::VBox->new(FALSE,1);
my $label_info = Gtk2::Label->new();
$label_info->set_markup( &make_label('Filename','Dimensions','Size'));
$hbox0->pack_start($label_info,FALSE,FALSE,1);
$vbox->pack_start($hbox0,0,0,0);
my $hbox = Gtk2::HBox->new(0,5);
#these vboxs will return the bulk of the gui
my $tbox = &ret_tree(); #the dir selector
$hbox->pack_start($tbox,0,0,0);
my ($cbox,$can) = &ret_can(); #thumbnail canvas
$hbox->pack_start($cbox,0,0,0);
my ($zbox,$can1) = &ret_can1(); #main image canvas
$hbox->pack_start($zbox,1,1,1);
$vbox->pack_start($hbox,1,1,0);
#add and show the vbox
$window->add($vbox);
$window->show_all();
#our main event-loop
Gtk2->main();
###################################################################
sub make_label{
my ($name, $dimensions, $size) = @_;
return
"<span background = 'yellow' foreground= 'black' size ='10000'><i> $name </i></span>".
"<span background = 'black' foreground= 'green' size ='20000'><i> $dimensions </i></span>".
"<span background = 'blue' foreground= 'red' size ='20000'><i> $size </i></span>";
}
#################################################################
sub ret_tree {
my $vbox = Gtk2::VBox->new(FALSE,5);
#create a scrolled window that will host the treeview
my $sw = Gtk2::ScrolledWindow->new (undef, undef);
$sw->set_shadow_type ('etched-out');
$sw->set_policy ('automatic','always');
$sw->set_placement('top-right');
$sw->set_size_request (200, 300);
$sw->set_border_width(0);
my $tree_store = Gtk2::TreeStore->new(qw/Glib::String/);
my %tree = %{ hashdir() };
#fill it with data
foreach my $key (sort keys %tree ) {
#the iter is a pointer in the treestore. We
#use to add data.
my $iter = $tree_store->append(undef);
$tree_store->set ($iter,0 => $key);
#need recursive sub here to nest subdirs
&recurse($tree_store, $tree{$key} , $iter );
}
#this will create a treeview, specify $tree_store as its model
my $tree_view = Gtk2::TreeView->new($tree_store);
#create a Gtk2::TreeViewColumn to add to $tree_view
my $tree_column = Gtk2::TreeViewColumn->new();
$tree_column->set_title('Select');
#create a renderer that will be used to display info
#in the model
my $renderer = Gtk2::CellRendererText->new;
#add this renderer to $tree_column. This works like a Gtk2::Hbox
# so you can add more than one renderer to $tree_column
$tree_column->pack_start ($renderer, FALSE);
# set the cell "text" attribute to column 0
#- retrieve text from that column in treestore
# Thus, the "text" attribute's value will depend on the row's value
# of column 0 in the model($treestore),
# and this will be displayed by $renderer,
# which is a text renderer
$tree_column->add_attribute($renderer, text => 0);
#add $tree_column to the treeview
$tree_view->append_column ($tree_column);
$sw->add($tree_view);
$tree_view->get_selection->signal_connect(
changed =>\&cell_selected,$tree_store );
#$tree_view->expand_all;
# expand only first level
$tree_view->expand_row (Gtk2::TreePath->new(0),0);
$vbox->pack_start($sw,1,1,0);
$vbox->show_all();
return $vbox;
}
######################################################################
sub ret_can {
my $vbox = Gtk2::VBox->new(FALSE,5);
#create a scrolled window that will host the treeview
my $sw = Gtk2::ScrolledWindow->new (undef, undef);
$sw->set_shadow_type ('etched-out');
$sw->set_policy ('automatic', 'always');
$sw->set_placement('top-right');
$sw->set_size_request (130, 300);
$sw->set_border_width(0);
my $canvas = Gnome2::Canvas->new_aa;
$canvas->set_scroll_region( 0,0,10,2000);
my $black = Gtk2::Gdk::Color->new (0x0000,0x0000,0x0000);
$canvas->modify_bg('normal',$black);
$canvas->set_center_scroll_region (FALSE);
$sw->add($canvas);
$vbox->pack_start($sw,TRUE,TRUE,0);
$vbox->show_all();
return ($vbox,$canvas);
}
######################################################################
sub ret_can1{
my $vbox = Gtk2::VBox->new(TRUE,5);
#create a scrolled window that will host the thumb canvas
my $sw = Gtk2::ScrolledWindow->new (undef, undef);
$sw->set_shadow_type ('etched-out');
$sw->set_policy ('always', 'always');
$sw->set_placement('top-right');
$sw->set_size_request (300, 300);
$sw->set_border_width(0);
my $canvas = Gnome2::Canvas->new_aa;
$canvas->set_scroll_region( 0,0,2000,2000);
my $black = Gtk2::Gdk::Color->new (0x0000,0x0000,0x0000);
$canvas->modify_bg('normal',$black);
$canvas->set_center_scroll_region (FALSE);
$sw->add($canvas);
$vbox->pack_start($sw,TRUE,TRUE,0);
$vbox->show_all();
return ($vbox,$canvas);
}
######################################################################
sub recurse{
my ( $tree_store, $hashref , $iter ) = @_;
my %hash = %{$hashref};
foreach my $key (sort keys %hash ){
my $iter_child = $tree_store->append($iter);
if( scalar (keys %hash == 0 ) ){
$tree_store->set ($iter_child,0 => $key );
}else{
$tree_store->set ($iter_child,0 => $key );
&recurse($tree_store, $hash{$key}, $iter_child);
}
}
}
###################################################################
sub cell_selected{
my ($tree_selection,$model ) = @_ ;
my $sel = $tree_selection->get_selected_rows;
my $value='';
if( defined $sel ){
my $path = $sel->to_string;
my @path_ele = split /:/, $path;
#reconstruct filesystem path from model path
while( @path_ele ){
$path = join ':', @path_ele;
#print "path $path\n";
my $iter = $model->get_iter_from_string($path);
my $val = $model->get($iter,0);
$value = $val.'/'.$value;
pop @path_ele;
}
}
#print "$value\n";
add_dir_contents("./$value");
return FALSE;
}
#############################################################
sub hashdir {
my $dir = shift || '.';
opendir my $dh, $dir or die $!;
my $tree = {}->{$dir} = {};
while ( my $file = readdir($dh) ) {
next if $file =~ m[^\.{1,2}$];
my $path = $dir . '/' . $file;
if(-d $path){
$tree->{$file} = hashdir($path);
}else{ next }
}
return $tree;
}
#########################################################
sub add_dir_contents {
my $path = $_[0];
#this decode utf8 routine is used so filenames with extended
# ascii characters (unicode) in filenames, will work properly
use Encode;
opendir my $dh, $path or warn "Error: $!";
my @files = grep !/^\.\.?$/, readdir $dh;
closedir $dh;
@files = map { decode( 'utf8', "$path/".$_ ) } sort @files;
my @thumbs=();
foreach my $file (@files) {
$file =~ s|//|/|g;
(my $text = $file ) =~ s|^.*/||g;
if( $file =~ /.*\.(png|jpg|gif)$/ ){ push @thumbs, $file }
}
#print "@thumbs\n";
load_thumbs( \ thumbs );
}
###############################################################
sub load_thumbs{
my $thumbsref = shift;
#clean out old thumbs
foreach my $item ( @{$can->{'temp'}} ){ $item->destroy; }
@{$can->{'temp'}} =();
my $root = $can->root;
my $count = 0;
foreach my $file( @$thumbsref ){
my $pixbuf_t = Gtk2::Gdk::Pixbuf->new_from_file_at_scale($file,100,100,1);
my $image = Gnome2::Canvas::Item->new ($root,
'Gnome2::Canvas::Pixbuf',
pixbuf => $pixbuf_t,
x => 2.0,
y => $count * 108,
width => 100,
height => $pixbuf_t->get_height,
anchor => 'nw',
);
$image->{'filepath'} = $file; #data rider to hold path
$image->signal_connect (event => sub {
my ($item, $event) = @_;
if( $event->type eq 'button-press' ){
&display_image( $image->{'filepath'} );
}
});
my $line = Gnome2::Canvas::Item->new ($root,
'Gnome2::Canvas::Line',
points => [0.0, $count * 108, 130.0, $count * 108],
fill_color => '#ff0000',
width_units => 6.0,
);
push @{$can->{'temp'}}, $image; #list to delete on refresh
push @{$can->{'temp'}}, $line;
$count++;
}
#print @{$can->{'temp'}},"\n";
#display_image( ${$can->{'temp'}}[0] ); #display first image in list
$can->set_scroll_region (0, 0, 10, $count * 108);
$can->scroll_to (0, 0);
}
##############################################################
sub display_image{
if( ref $can1->{'temp'} eq 'Gnome2::Canvas::Pixbuf' ){
$can1->{'temp'}->destroy}
my $im = Gtk2::Gdk::Pixbuf->new_from_file( $_[0] );
my $x = $im->get_width;
my $y = $im->get_height;
my $image = Gnome2::Canvas::Item->new ($can1->root,
'Gnome2::Canvas::Pixbuf',
pixbuf => $im,
x => 5.0,
y => 5.0,
width => $x,
height => $y,
anchor => 'nw',
);
$can1->{'temp'} = $image;
$can1->set_scroll_region (0, 0, $x + 10, $y + 10);
$can1->scroll_to (0, 0);
# set to clipboard for menu or mouse paste
$clipboard->clear;
$clipboard1->clear;
$clipboard->set_text($_[0]);
$clipboard1->set_text($_[0]);
my $filebase = substr ($_[0], rindex ($_[0], "/") + 1);
$label_info->set_markup( &make_label( $filebase, "$x x $y" , (stat $_[0] )[7] ));
}
##################################################################
__END__
zentara
--
I'm not really a human, but I play one on earth.
http://zentara.net/japh.html
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]