Re: Editor application with grid
- From: zentara <zentara1 sbcglobal net>
- To: gtk-perl-list gnome org
- Subject: Re: Editor application with grid
- Date: Sun, 17 Sep 2006 08:19:16 -0400
On Sun, 17 Sep 2006 03:09:16 +0200
Dieter Schicker <dieter schicker uni-graz at> wrote:
I'm planning to implement an editor application where I want to give
users the ability to drag together different types of widgets on a grid.
I wanted to do it in Java, but now after some weeks of experience with
gtk perl I would really like to implement it with Gtk.
Has anybody done something similar already? Any hints?
Anytime I hear the word "drag", I think to use the Canvas.
It's pretty easy to drag items on a canvas, then detect what
occupies a certain rectangular region. But you said
"drag together different types of widgets", which is a harder
problem.
Here is a simple example which I ripped from the canvas demo.
I use ellipses, but you could use text items instead.
You could also add "data-riders" to each item (similar to tags),
to move groups of items together, that would be a bit more complex.
Otherwise, there is the "testdnd" script in the examples subdir
of the Gtk2 module.
#!/usr/bin/perl
use warnings;
use strict;
use Gnome2::Canvas;
use Gtk2::Gdk::Keysyms;
use Glib qw(TRUE FALSE);
use constant M_PI => 3.141529;
# control anti-aliasing by setting a 0 or 1
my $aa = 1; # 0 for no anti-alias
sub zoom_changed {
my ($adj, $canvas) = @_;
$canvas->set_pixels_per_unit ($adj->value);
}
my $dragging = FALSE;
my ($x, $y);
sub item_event {
my ($item, $event) = @_;
# set item_[xy] to the event x,y position in the parent's
# item-relative coordinates
my ($item_x, $item_y) = $item->parent->w2i ($event->coords);
if ($event->type eq 'button-press') {
if ($event->button == 1) {
if ($event->state >= 'shift-mask') {
$item->destroy;
} else {
$x = $item_x;
$y = $item_y;
$item->grab ([qw/pointer-motion-mask
button-release-mask/],
Gtk2::Gdk::Cursor->new ('fleur'),
$event->time);
$dragging = TRUE;
}
} elsif ($event->button == 2) {
if ($event->state >= 'shift-mask') {
$item->lower_to_bottom;
} else {
$item->lower (1);
}
} elsif ($event->button == 3) {
if ($event->state >= 'shift-mask') {
$item->raise_to_top;
} else {
$item->raise (1);
}
}
} elsif ($event->type eq 'motion-notify') {
if ($dragging && $event->state >= 'button1-mask') {
my $new_x = $item_x;
my $new_y = $item_y;
$item->move ($new_x - $x, $new_y - $y);
$x = $new_x;
$y = $new_y;
}
} elsif ($event->type eq 'button-release') {
$item->ungrab ($event->time);
$dragging = FALSE;
}
return FALSE;
}
sub setup_item {
my $item = shift;
$item->signal_connect (event => \&item_event);
}
my $gray50_width = 2;
my $gray50_height = 2;
my $gray50_bits = pack "CC", 0x02, 0x01;
sub setup_ellipses {
my $root = shift;
if ($root->canvas->aa) {
setup_item (Gnome2::Canvas::Item->new ($root,
'Gnome2::Canvas::Ellipse',
"x1", 210.0,
"y1", 80.0,
"x2", 280.0,
"y2", 140.0,
"fill_color_rgba", 0x3cb37180,
"outline_color", "black",
"width_pixels", 0));
} else {
my $stipple = Gtk2::Gdk::Bitmap->create_from_data
(undef, $gray50_bits, $gray50_width, $gray50_height);
setup_item (Gnome2::Canvas::Item->new ($root,
'Gnome2::Canvas::Ellipse',
"x1", 210.0,
"y1", 80.0,
"x2", 280.0,
"y2", 140.0,
"fill_color", "cadetblue",
"fill_stipple", $stipple,
"outline_color", "black",
"width_pixels", 0));
}
if ($root->canvas->aa) {
setup_item (Gnome2::Canvas::Item->new ($root,
'Gnome2::Canvas::Ellipse',
"x1", 310.0,
"y1", 80.0,
"x2", 380.0,
"y2", 140.0,
"fill_color_rgba", 0xb3713c80,
"outline_color", "black",
"width_pixels", 0));
} else {
my $stipple = Gtk2::Gdk::Bitmap->create_from_data
(undef, $gray50_bits, $gray50_width, $gray50_height);
setup_item (Gnome2::Canvas::Item->new ($root,
'Gnome2::Canvas::Ellipse',
"x1", 310.0,
"y1", 80.0,
"x2", 380.0,
"y2", 140.0,
"fill_color", "brown",
"fill_stipple", $stipple,
"outline_color", "black",
"width_pixels", 0));
}
if ($root->canvas->aa) {
setup_item (Gnome2::Canvas::Item->new ($root,
'Gnome2::Canvas::Ellipse',
"x1", 210.0,
"y1", 180.0,
"x2", 280.0,
"y2", 240.0,
"fill_color_rgba", 0x5f9ea080,
"outline_color", "black",
"width_pixels", 0));
} else {
my $stipple = Gtk2::Gdk::Bitmap->create_from_data
(undef, $gray50_bits, $gray50_width, $gray50_height);
setup_item (Gnome2::Canvas::Item->new ($root,
'Gnome2::Canvas::Ellipse',
"x1", 210.0,
"y1", 180.0,
"x2", 280.0,
"y2", 240.0,
"fill_color", "green",
"fill_stipple", $stipple,
"outline_color", "black",
"width_pixels", 0));
}
if ($root->canvas->aa) {
setup_item (Gnome2::Canvas::Item->new ($root,
'Gnome2::Canvas::Ellipse',
"x1", 310.0,
"y1", 180.0,
"x2", 380.0,
"y2", 240.0,
"fill_color_rgba", 0xff9ea080,
"outline_color", "black",
"width_pixels", 0));
} else {
my $stipple = Gtk2::Gdk::Bitmap->create_from_data
(undef, $gray50_bits, $gray50_width, $gray50_height);
setup_item (Gnome2::Canvas::Item->new ($root,
'Gnome2::Canvas::Ellipse',
"x1", 310.0,
"y1", 180.0,
"x2", 380.0,
"y2", 240.0,
"fill_color", "pink",
"fill_stipple", $stipple,
"outline_color", "black",
"width_pixels", 0));
}
}
use constant VERTICES => 10;
use constant RADIUS => 60.0;
use constant SCALE => 7.0;
sub key_press {
my ($canvas, $event) = @_;
my ($x, $y) = $canvas->get_scroll_offsets;
if ($event->keyval == $Gtk2::Gdk::Keysyms{Up}) {
$canvas->scroll_to ($x, $y - 20);
} elsif ($event->keyval == $Gtk2::Gdk::Keysyms{Down}) {
$canvas->scroll_to ($x, $y + 20);
} elsif ($event->keyval == $Gtk2::Gdk::Keysyms{Left}) {
$canvas->scroll_to ($x - 10, $y);
} elsif ($event->keyval == $Gtk2::Gdk::Keysyms{Right}) {
$canvas->scroll_to ($x + 10, $y);
} else {
return FALSE;
}
return TRUE;
}
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
#gtk_widget_push_colormap (gdk_rgb_get_cmap ());
#### FIXME
### Gtk2::Widget->push_colormap (Gtk2::Gdk::Rgb->get_cmap);
my $canvas = $aa ? Gnome2::Canvas->new_aa : Gnome2::Canvas->new;
my $white = Gtk2::Gdk::Color->new (0xFFFF,0xFFFF,0xFFFF);
$canvas->modify_bg('normal',$white);
$canvas->set_center_scroll_region (FALSE);
# Setup canvas items
my $root = $canvas->root;
setup_ellipses ($root);
# 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;
}
Gtk2->init;
my $mw = Gtk2::Window->new;
$mw->signal_connect (delete_event => sub { Gtk2->main_quit; 1 });
$mw->add( create($aa) ); # 0 no anti-alias , 1 yes
$mw->show;
Gtk2->main;
__END__
--
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]