#!/usr/bin/perl use warnings; use strict; use Gnome2::Canvas; my $image_in = shift or die "No Image $!\n"; package CanvasPrimitives; use strict; use Gnome2::Canvas; use Gtk2::Gdk::Keysyms; use Glib qw(TRUE FALSE); use constant M_PI => 3.141529; sub zoom_changed { my ($adj, $canvas) = @_; $canvas->set_pixels_per_unit ($adj->value); } my $dragging = FALSE; #my ($x, $y); my ($last_x, $last_y); sub item_event { my ( $item, $event ) = @_; print "$item $event\n"; if ( $event->type eq "button-press" ) { $item->raise_to_top(); $item->grab ([qw/pointer-motion-mask button-release-mask/], Gtk2::Gdk::Cursor->new ('fleur'), $event->time); $last_x = $event->x; $last_y = $event->y; $dragging = 1; } elsif ( $event->type eq "motion-notify" ) { if ($dragging) { my $new_x = $event->x; my $new_y = $event->y; $item->move( $new_x - $last_x, $new_y - $last_y ); $last_x = $new_x; $last_y = $new_y; } } elsif ( $event->type eq "button-release" ) { $item->ungrab ($event->time); $dragging = 0; } return 0; } sub setup_item { my $item = shift; $item->signal_connect (event => \&item_event); } sub setup_texts { my $root = shift; my $text1 = Gnome2::Canvas::Item->new ($root, 'Gnome2::Canvas::Text', "text", "Anchor NW", "x", 50.0, "y", 50.0, "font", "Sans Bold 24", "anchor", 'GTK_ANCHOR_NW', "fill_color_rgba", 0x0000ff80); my $text2 = Gnome2::Canvas::Item->new ($root, 'Gnome2::Canvas::Text', "text", "Multiline text", "x", 200.0, "y", 150.0, #"font", "monospace bold 14", "font", "Sans Bold 24", "anchor", 'GTK_ANCHOR_NW', #"justification", 'GTK_JUSTIFY_CENTER', "fill_color", "firebrick"); my $text3 = Gnome2::Canvas::Item->new ($root, 'Gnome2::Canvas::Text', "text", "Clipped text\nClipped text\nClipped text\nClipped text\nClipped text\nClipped text", "x", 400.0, "y", 250.0, "font", "Sans 12", "anchor", 'GTK_ANCHOR_SE', "clip", TRUE, "clip_width", 50.0, "clip_height", 55.0, "x_offset", 10.0, "fill_color", "darkgreen"); setup_item ($text1); setup_item ($text2); setup_item ($text3); } sub setup_images { my ($root, $aa) = @_; eval { my $im = Gtk2::Gdk::Pixbuf->new_from_file($image_in); my $image = Gnome2::Canvas::Item->new ($root, 'Gnome2::Canvas::Pixbuf', pixbuf => $im, x => 100.0, y => 225.0, width => $im->get_width, height => $im->get_height, anchor => 'center', ); setup_item ($image); } } use constant SCALE => 7.0; sub create { my $aa = shift; my $vbox = Gtk2::VBox->new (FALSE, 4); $vbox->set_border_width (4); $vbox->show; my $w = Gtk2::Label->new ("Drag an item with button 1. Click button 2 on an item to lower it,\n" . "or button 3 to raise it. Shift+click with buttons 2 or 3 to send\n" . "an item to the bottom or top, respectively."); $vbox->pack_start ($w, FALSE, FALSE, 0); $w->show; my $hbox = Gtk2::HBox->new (FALSE, 4); $vbox->pack_start ($hbox, FALSE, FALSE, 0); $hbox->show; # Create the canvas my $canvas = Gnome2::Canvas->new_aa; $canvas->set_center_scroll_region (FALSE); # Setup canvas items my $root = $canvas->root; setup_texts ($root, $aa); setup_images ($root, $aa); # Zoom $w = Gtk2::Label->new ("Zoom:"); $hbox->pack_start ($w, FALSE, FALSE, 0); $w->show; my $adj = Gtk2::Adjustment->new (1.00, 0.05, 5.00, 0.05, 0.50, 0.50); $adj->signal_connect (value_changed => \&zoom_changed, $canvas); $w = Gtk2::SpinButton->new ($adj, 0.0, 2); $w->set_size_request (50, -1); $hbox->pack_start ($w, FALSE, FALSE, 0); $w->show; # Layout the stuff my $table = Gtk2::Table->new (2, 2, FALSE); $table->set_row_spacings (4); $table->set_col_spacings (4); $vbox->pack_start ($table, TRUE, TRUE, 0); $table->show; my $frame = Gtk2::Frame->new; $frame->set_shadow_type ('in'); $table->attach ($frame, 0, 1, 0, 1, [qw/expand fill shrink/], [qw/expand fill shrink/], 0, 0); $frame->show; $canvas->set_size_request (600, 450); $canvas->set_scroll_region (0, 0, 600, 450); $frame->add ($canvas); $canvas->show; $canvas->signal_connect_after (key_press_event => \&key_press); $w = Gtk2::HScrollBar->new ($canvas->get_hadjustment); $table->attach ($w, 0, 1, 1, 2, [qw/expand fill shrink/], [qw/fill/], 0, 0); $w->show;; $w = Gtk2::VScrollBar->new ($canvas->get_vadjustment); $table->attach ($w, 1, 2, 0, 1, ['fill'], [qw/expand fill shrink/], 0, 0); $w->show; $canvas->set_flags ('can-focus'); $canvas->grab_focus; return $vbox; } 1; sub create_canvas { my $app = Gtk2::Window->new; $app->signal_connect (delete_event => sub { Gtk2->main_quit; 1 }); my $can = CanvasPrimitives::create(); $app->add ($can); $app->show; } Gtk2->init; create_canvas (); Gtk2->main; #### #!/usr/bin/perl use warnings; use Tk; use Tk::JPEG; use Tk::Zinc; use MIME::Base64; #my $imagein = shift || '1z-squatch.jpg'; my $imagein = shift || "No Image $!\n" ; my $mw = MainWindow->new(); $mw->idletasks; my $jscreen = $mw->screenwidth - 500; my $kscreen = $mw->screenheight - 500; $mw->geometry( "$jscreen" . "x" . "$kscreen" . "+20+20" ); # Only tested with jpeg. open( PIC, $imagein ) or die print "Need a jpeg \n"; binmode(PIC); my $buffer = ''; while () { $buffer .= $_; } close(PIC); my $image = encode_base64($buffer); my $zinc = $mw->Scrolled( 'Zinc', -scrollbars => 'osoe', -borderwidth => 0 )->pack( -side => 'left', -fill => 'both', -expand => 1 ); my $zoomframe = $mw->Frame()->pack( -side => 'left', -fill => 'y' ); my $label1 = $zoomframe->Label( -text => 'Zoom' )->pack( -side => 'top', -pady => 5 ); my $button1 = $zoomframe->Button( -text => '+', -command => [ \&zoom, 1 ] )->pack( -side => 'top', -pady => 5, -fill => 'x' ); my $button2 = $zoomframe->Button( -text => '-', -command => [ \&zoom, 0 ] )->pack( -side => 'top', -pady => 5, -fill => 'x' ); my $scale = 0; my $radio1 = $zoomframe->Radiobutton( -text => 'Resize', -variable => \$scale, -value => 0, -command => \&reset )->pack( -side => 'top', -pady => 5, -fill => 'x' ); my $radio2 = $zoomframe->Radiobutton( -text => 'Scale', -variable => \$scale, -value => 1, -command => \&reset )->pack( -side => 'top', -pady => 5, -fill => 'x' ); my $percent = '100%'; my $label2 = $zoomframe->Label( -textvariable => \$percent )->pack( -side => 'top', -pady => 5 ); my $factor1 = 4; my $factor2 = 4; my $photo = $zinc->Photo( -data => $image, -format => 'jpeg' ); my $group = $zinc->add( 'group', 1 ); my $realimage = $zinc->add( 'icon', $group, -position => [ 0, 0 ], -image => $photo, -tags => 'image' ); $zinc->configure( -scrollregion => [ $zinc->bbox('image') ] ); MainLoop; sub reset { $factor1 = 4; $factor2 = 4; $percent = '100%'; $zinc->remove('image'); $zinc->xview( 'moveto', 0 ); $zinc->yview( 'moveto', 0 ); $zinc->remove( 'group', 1 ); $group = $zinc->add( 'group', 1 ); $realimage = $zinc->add( 'icon', $group, -position => [ 0, 0 ], -image => $photo, -tags => 'image' ); $zinc->configure( -scrollregion => [ $zinc->bbox('image') ] ); } sub zoom { my ($zoomer) = @_; if ( $zoomer == 0 && $factor1 == 1 ) { return; } $mw->Busy; if ( $scale == 0 ) { if ($realimage) { $zinc->remove('image'); undef($realimage); } if ($zoomimage) { $zoomimage->delete; undef($zoomimage); } if ($subbedimage) { $subbedimage->delete; undef($subbedimage); } $zoomimage = $zinc->Photo; $subbedimage = $zinc->Photo; $zoomimage->blank; $subbedimage->blank; if ( $zoomer == 1 ) { $factor1++; } else { $factor1--; } $zoomimage->copy( $photo, -zoom => $factor1 ); $subbedimage->copy( $zoomimage, -subsample => $factor2 ); $zinc->xview( 'moveto', 0 ); $zinc->yview( 'moveto', 0 ); $realimage = $zinc->add( 'icon', $group, -position => [ 0, 0 ], -image => $subbedimage, -tags => 'image' ); $zinc->configure( -scrollregion => [ $zinc->bbox('image') ] ); } else { if ( $zoomer == 1 ) { $factor1++; } else { $factor1--; } my $newscale = $factor1 / $factor2; $zinc->xview( 'moveto', 0 ); $zinc->yview( 'moveto', 0 ); $zinc->scale( $group, $newscale, $newscale ); $zinc->configure( -scrollregion => [ $zinc->bbox('image') ] ); } $mw->Unbusy; $mw->update; $percent = ( ( $factor1 / $factor2 ) * 100 ) . '%'; }