view release on metacpan or search on metacpan
The changes are logged onto the SVN, which is at
http://trac.osgeo.org/geoinformatica/
Moved to svn.osgeo.org
Date: 23:45:18, 21. elokuuta 2008
overlay's parameters can be set at glue's constructor
Date: 23:44:01, 21. elokuuta 2008
default single color can be set from outside
Date: 22:37:18, 21. elokuuta 2008
layer treeview tooltips and "v" instead of "?"
Date: 13:14:45, 21. elokuuta 2008
default single color is black now
Date: 17:24:44, 1. elokuuta 2007
handle the case where ctrl is down and selection is null
Date: 10:59:43, 1. elokuuta 2007
update features dialog in concert with selection
Date: 22:57:54, 31. heinäkuuta 2007
reselect = send signal new_selection
Date: 16:43:36, 31. heinäkuuta 2007
do not maintain selected layer in overlay; new signal new_selection (preferred over features_selected)
Date: 22:01:28, 20. heinäkuuta 2007
use Gtk2::Gdk::Color->new and not new Gtk2::Gdk::Color
Date: 19:52:08, 19. heinäkuuta 2007
delete rubberband attribute in button_release_event if measure path, prevents erasing the path in motion_notify (maybe this is not fixing in the right place)
Date: 19:50:24, 19. heinäkuuta 2007
fixed a typo in Layer.defaults; initialize COLOR_TABLE attribute in color_table method if setting from GDAL color_table; use Gtk2::Gdk::Color->new and not new Gtk2::Gdk::Color
Date: 21:49:04, 15. heinäkuuta 2007
update_image in delete_rubberband but not in add_to_selection; in rubberband_value use Geo::OGC methods
Date: 19:20:52, 14. heinäkuuta 2007
rubberband_mode and rubberband_geometry; call update image after reselect; new image menu item "select containing"
Date: 19:18:51, 14. heinäkuuta 2007
selected_features gets or sets (doesn't add); after unselect all call update_image
Date: 19:17:33, 14. heinäkuuta 2007
divide overlay's rubberbanding into rubberband_mode and rubberband_geometry; remove backup pixmap; new methods: add_to_selection, reset_image and reset_pixmap; be more careful with creating selection
Date: 19:13:38, 14. heinäkuuta 2007
divide overlay's rubberbanding into rubberband_mode and rubberband_geometry
Date: 0:15:26, 14. heinäkuuta 2007
code to allow user create geometry collections
Date: 19:56:18, 12. heinäkuuta 2007
now uses Geo::OGC::Geometry
Date: 19:55:21, 12. heinäkuuta 2007
new methods in Layer: features_selected (also an attribute), selected_features, and features
Date: 1:39:57, 10. heinäkuuta 2007
show toolbar button, change cursor when popup menu on layer list
Date: 1:38:35, 10. heinäkuuta 2007
test registering commands
Date: 23:37:45, 9. heinäkuuta 2007
simple named params for register_function
Date: 23:08:33, 9. heinäkuuta 2007
simpler overlay menu
Date: 23:07:11, 9. heinäkuuta 2007
new methods: inspect_data, schema
Date: 23:04:15, 9. heinäkuuta 2007
simpler overlay menu
Date: 23:02:09, 9. heinäkuuta 2007
test layer class
Date: 18:07:02, 9. heinäkuuta 2007
removed draw_on and event_handler code mostly (should use signals)
Date: 17:16:03, 9. heinäkuuta 2007
moved p and plot to IPC::Gnuplot
}
# visible layer list
my $list = Gtk2::ScrolledWindow->new();
$list->set_policy("never", "automatic");
$list->add($app->{tree_view});
# a panel with the layer list and the map
my $hbox = Gtk2::HPaned->new();
$hbox->add1($list);
$hbox->add2($app->{overlay});
# stack all GUI elements vertically
my $vbox = Gtk2::VBox->new(FALSE, 0);
$vbox->pack_start($app->{toolbar}, FALSE, FALSE, 0);
$vbox->pack_start($hbox, TRUE, TRUE, 0);
$vbox->pack_start($app->{entry}, FALSE, FALSE, 0);
$vbox->pack_start($app->{statusbar}, FALSE, FALSE, 0);
$window->add($vbox);
$window->signal_connect("destroy", \&my_destroy);
The Gtk2::Ex::Geo modules provide a plaform for developing geospatial
applications. The idea is to provide a canvas for geospatial data,
a set of dialogs, and glue code.
The tools build the abstract geospatial data layer defined by the
Geo::Layer module.
\section index_geg_glue Gtk2::Ex::Geo::Glue
A glue object manages the GUI. The dialog boxes of the registered
layer classes can be obtained from it. It maintains an overlay.
\section index_cli The CLI in an entry
The entry widget that is managed by a glue object is used for getting
commands from the user. The glue object maintains a history of the
objects. Old commands can be browsed with the arrow up and arrow down
keys. The user command is givent to Perl's eval function.
1) the variable names are inspected and found layer names are replaced
with pointers to real layers
\section index_geg_dialogs Gtk2::Ex::Geo::Layer
The root class of all layer classes.
Layer classes should be registered with the glue object. The
registration information comprises a dialogs object (an instance of
DialogMaster or its subclass), and class methods it offers (typically
a subset of 'new', 'open', 'save', etc.).
\section index_geg_overlay Gtk2::Ex::Geo::Overlay
An overlay is a widget, subclassed from Gtk2::ScrolledWindow. An
overlay contains a list of layers, which it renders on a canvas, which
it puts into its window.
Rubberbanding and keyboard zoom-in (with + key), zoom-out (with -
key), and panning (with arrow keys) is built-in.
\section index_geg_dialogs Gtk2::Ex::Geo::Dialogs
*/
lib/Gtk2/Ex/Geo/Dialogs/Colors.pm view on Meta::CPAN
# button callbacks
##@ignore
sub apply_colors {
my($self, $gui, $close) = @{$_[1]};
my @color = split(/ /, $self->{colors_dialog}->get_widget('border_color_label')->get_text);
my $has_border = $self->{colors_dialog}->get_widget('border_color_checkbutton')->get_active();
@color = () unless $has_border;
$self->border_color(@color);
$self->hide_dialog('colors_dialog') if $close;
$gui->{overlay}->render;
}
##@ignore
sub cancel_colors {
my($self, $gui);
for (@_) {
next unless ref eq 'ARRAY';
($self, $gui) = @{$_};
}
$self->palette_type($self->{backup}->{palette_type});
lib/Gtk2/Ex/Geo/Dialogs/Colors.pm view on Meta::CPAN
$self->hue_range(@{$self->{backup}->{hue_range}});
$self->grayscale_subtype($self->{backup}->{grayscale_subtype});
$self->invert_scale($self->{backup}->{invert_scale});
$self->grayscale_color(@{$self->{backup}->{grayscale_color}});
$self->border_color(@{$self->{backup}->{border_color}});
$self->hide_dialog('colors_dialog');
$gui->{overlay}->render;
1;
}
##@ignore
sub copy_colors {
my($self, $gui) = @{$_[1]};
my $table = copy_colors_dialog($self, $gui);
if ($table) {
my $palette_type = $self->palette_type;
if ($palette_type eq 'Color table') {
lib/Gtk2/Ex/Geo/Dialogs/Colors.pm view on Meta::CPAN
my $i = 0;
for my $column ('Layer') {
my $cell = Gtk2::CellRendererText->new;
my $col = Gtk2::TreeViewColumn->new_with_attributes($column, $cell, text => $i++);
$treeview->append_column($col);
}
$model->clear;
my @names;
for my $layer (@{$gui->{overlay}->{layers}}) {
next if $layer->name() eq $self->name();
push @names, $layer->name();
$model->set ($model->append(undef), 0, $layer->name());
}
#$dialog->move(@{$self->{colors_from_position}}) if $self->{colors_from_position};
$dialog->get_widget('colors_from_dialog')->show_all;
$dialog->get_widget('colors_from_dialog')->present;
my $response = $dialog->get_widget('colors_from_dialog')->run;
my $table;
if ($response eq 'ok') {
my @sel = $treeview->get_selection->get_selected_rows;
if (@sel) {
my $i = $sel[0]->to_string if @sel;
my $from_layer = $gui->{overlay}->get_layer_by_name($names[$i]);
if ($palette_type eq 'Color table') {
$table = $from_layer->color_table();
} elsif ($palette_type eq 'Color bins') {
$table = $from_layer->color_bins();
}
}
}
lib/Gtk2/Ex/Geo/Dialogs/Labeling.pm view on Meta::CPAN
$labeling->{min_size} = $dialog->get_widget('labels_min_size_entry')->get_text;
$labeling->{font} = $dialog->get_widget('labels_font_label')->get_text;
@{$labeling->{color}} = split(/ /, $dialog->get_widget('labels_color_label')->get_text);
$labeling->{min_size} = $dialog->get_widget('labels_min_size_entry')->get_text;
$labeling->{incremental} = $dialog->get_widget('labels_incremental_checkbutton')->get_active();
$self->labeling($labeling);
$self->hide_dialog('labels_dialog') if $close;
$gui->set_layer($self);
$gui->{overlay}->render;
}
##@ignore
sub cancel_labels {
my($self, $gui);
for (@_) {
next unless ref eq 'ARRAY';
($self, $gui) = @{$_};
}
$self->labeling($self->{labeling_backup});
$self->hide_dialog('labels_dialog');
$gui->set_layer($self);
$gui->{overlay}->render;
1;
}
##@ignore
sub labels_font {
my($self, $gui) = @{$_[1]};
my $font_chooser = Gtk2::FontSelectionDialog->new ("Select font for the labels");
my $font_name = $self->{labels_dialog}->get_widget('labels_font_label')->get_text;
$font_chooser->set_font_name($font_name);
if ($font_chooser->run eq 'ok') {
lib/Gtk2/Ex/Geo/Dialogs/Symbols.pm view on Meta::CPAN
$self->symbol_field($field) if defined $field;
my $scale_min = $dialog->get_widget('symbols_scale_min_entry');
my $scale_max = $dialog->get_widget('symbols_scale_max_entry');
$self->symbol_scale($scale_min->get_text(), $scale_max->get_text());
my $size_spin = $dialog->get_widget('symbols_size_spinbutton');
my $size = $size_spin->get_value();
$self->symbol_size($size);
$self->hide_dialog('symbols_dialog') if $close;
$gui->set_layer($self);
$gui->{overlay}->render;
}
##@ignore
sub cancel_symbols {
my($self, $gui);
for (@_) {
next unless ref CORE::eq 'ARRAY';
($self, $gui) = @{$_};
}
$self->symbol_type($self->{backup}->{symbol_type});
$self->symbol_field($self->{backup}->{symbol_field}) if $self->{backup}->{symbol_field};
$self->symbol_scale(@{$self->{backup}->{symbol_scale}});
$self->symbol_size($self->{backup}->{symbol_size});
$self->hide_dialog('symbols_dialog');
$gui->set_layer($self);
$gui->{overlay}->render;
1;
}
##@ignore
sub fill_symbol_type_combo {
my($self, $symbol_type) = @_;
$symbol_type = '' unless defined $symbol_type;
my $combo = $self->{symbols_dialog}->get_widget('symbols_type_combobox');
my $model = $combo->get_model;
$model->clear;
lib/Gtk2/Ex/Geo/Dialogs/Symbols.pm view on Meta::CPAN
my $combo = $self->{symbols_dialog}->get_widget('symbols_field_combobox');
($self->{index2symbol_field}{$combo->get_active()} or '');
}
##@ignore
sub fill_symbol_scale_fields {
my($self, $gui) = @{$_[1]};
my @range;
my $field = get_selected_symbol_field($self);
return if $field eq 'Fixed size';
my @r = $gui->{overlay}->get_viewport_of_selection;
@r = $gui->{overlay}->get_viewport unless @r;
eval {
@range = $self->value_range(field_name => $field, filter_rect => \@r);
};
if ($@) {
$gui->message("$@");
return;
}
$self->{symbols_dialog}->get_widget('symbols_scale_min_entry')->set_text($range[0]);
$self->{symbols_dialog}->get_widget('symbols_scale_max_entry')->set_text($range[1]);
}
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
$self->create_layer_tree_view;
($self->{toolbar}, $self->{mode_button}, $self->{geometry_button}) =
$self->create_toolbar;
$self->{statusbar} = Gtk2::Statusbar->new();
$self->{entry} = Gtk2::Entry->new();
$self->{entry}->signal_connect( key_press_event => \&eval_entry, $self );
$self->{overlay} = $self->create_overlay(@_);
$self->set_interaction_mode('Zoom');
($self->{history}, $self->{history_file}) = $self->open_history($params{history});
($self->{resources}, $self->{resources_file}) = $self->open_resources($params{resources});
my @buffer = <Gtk2::Ex::Geo::History::DATA>;
pop @buffer unless $buffer[$#buffer] =~ /^\</; # remove the extra content
shift @buffer if $buffer[0] =~ /^\s*$/;
register_dialogs($self, Gtk2::Ex::Geo::DialogMaster->new(buffer => \@buffer));
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
$self->{focused} = $layer;
}, $self);
$view->signal_connect
( motion_notify_event =>
sub {
my($self, $event, $gis) = @_;
$self->set_has_tooltip(0);
my @res = $self->get_path_at_pos($event->x, $event->y);
return unless $res[0] and defined $res[0]->to_string;
return unless $res[1];
my $layer = $gis->{overlay}->get_layer_by_index($res[0]->to_string);
my $column = $res[1]->get_title;
my $tooltip = $tooltips{$column}.': ';
for ($column) {
$tooltip .= $layer->name if /^name/;
$tooltip .= $layer->type('long') if /^type/;
$tooltip .= $layer->visible ? 'visible' : 'hidden' if /^v/;
$tooltip .= $layer->alpha if /^a/;
}
$self->set_tooltip_text($tooltip);
$self->set_has_tooltip(1);
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
$self->set_has_tooltip(0);
}) if Gtk2->CHECK_VERSION(2,12,0);
$view->signal_connect
( button_press_event => \&layer_menu, $self );
return ($view, $model);
}
sub layer_list_edit {
my($cell, $path, $new_value, $data) = @_;
my($self, $column) = @$data;
my $layer = $self->{overlay}->get_layer_by_index($path);
return unless $layer;
if ($column eq 'name') {
$layer->name($new_value) unless $self->{overlay}->get_layer_by_name($new_value);
} else {
$layer->alpha($new_value);
$self->update;
$self->{overlay}->render;
}
}
sub create_toolbar {
my($self) = @_;
my $toolbar = Gtk2::Toolbar->new();
my $button1 = Gtk2::ComboBox->new;
my $renderer = Gtk2::CellRendererText->new;
$button1->pack_start($renderer, TRUE);
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
$item->add($button1);
$toolbar->insert($item, 0);
my $button = Gtk2::ToolButton->new_from_stock('gtk-zoom-in');
my $tooltips = Gtk2::Tooltips->new;
my $tip = 'Zoom in one tenth.';
$button->set_tooltip($tooltips, $tip, '');
$tooltips->set_tip($button, $tip);
$tooltips->enable;
$toolbar->insert($button, -1);
$button->signal_connect('clicked', sub {$_[1]->{overlay}->zoom_in}, $self);
$button->show_all;
$button = Gtk2::ToolButton->new_from_stock('gtk-zoom-out');
$tooltips = Gtk2::Tooltips->new;
$tip = 'Zoom out one tenth.';
$button->set_tooltip($tooltips, $tip, '');
$tooltips->set_tip($button, $tip);
$tooltips->enable;
$toolbar->insert($button, -1);
$button->signal_connect('clicked', sub {$_[1]->{overlay}->zoom_out}, $self);
$button->show_all;
$button = Gtk2::ToolButton->new_from_stock('gtk-zoom-fit');
$tooltips = Gtk2::Tooltips->new;
$tip = 'Zoom to all.';
$button->set_tooltip($tooltips, $tip, '');
$tooltips->set_tip($button, $tip);
$tooltips->enable;
$toolbar->insert($button, -1);
$button->signal_connect('clicked', sub {$_[1]->{overlay}->zoom_to_all}, $self);
$button->show_all;
return ($toolbar, $button1, $button2);
}
sub _set_interaction_mode {
my($combo, $self) = @_;
my $model = $combo->get_model;
my $a = $combo->get_active();
my $iter = $model->get_iter_from_string($a);
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
$self->{geometry_button}->set_sensitive(1);
} elsif ($mode eq 'Draw') {
$self->set_interaction_geometry('Rectangle');
$self->{geometry_button}->set_sensitive(1);
} elsif ($mode eq 'Edit') {
$self->set_interaction_geometry('Line');
$self->{geometry_button}->set_sensitive(0);
} else {
$self->{geometry_button}->set_sensitive(1);
}
$self->{overlay}->{rubberband_mode} = lc($mode);
}
sub set_interaction_mode {
my($self, $mode) = @_;
my $model = $self->{mode_button}->get_model;
$model->foreach(\&set_combo_to, [$self->{mode_button}, $mode]);
}
sub _set_interaction_geometry {
my($combo, $self) = @_;
my $model = $combo->get_model;
my $a = $combo->get_active();
my $iter = $model->get_iter_from_string($a);
my $geometry = $model->get_value($iter);
$self->{overlay}->{rubberband_geometry} = lc($geometry);
}
sub set_interaction_geometry {
my($self, $geometry) = @_;
my $model = $self->{geometry_button}->get_model;
$model->foreach(\&set_combo_to, [$self->{geometry_button}, $geometry]);
}
sub create_overlay {
my($self, %params) = @_;
my $overlay = Gtk2::Ex::Geo::Overlay->new();
my($menu, $menu_item_setup) = overlay_menu();
my %overlay_params = ( menu => $menu,
menu_item_setup => $menu_item_setup,
rubberband_mode => 'zoom',
rubberband_geometry => 'rect',
selecting => 'that_intersect',
);
for my $key (keys %params) {
if ($key =~ /^overlay:(\w+)/) {
$overlay_params{$1} = $params{$key};
}
}
$overlay->my_inits( %overlay_params );
$overlay->signal_connect
( pixmap_ready => sub {
my($overlay, $gis) = @_;
my $layer = $self->get_selected_layer();
if ($layer) {
my $gc = Gtk2::Gdk::GC->new($overlay->{pixmap});
$gc->set_rgb_fg_color(Gtk2::Gdk::Color->new(65535,0,0));
$layer->render_selection($gc, $overlay);
}
}, $self);
$overlay->signal_connect
( new_selection =>
sub {
my(undef, $gis) = @_;
my $overlay = $gis->{overlay};
my $layer = $gis->get_selected_layer();
if ($layer) {
if ($overlay->{selection}) {
$layer->select($overlay->{selecting} => $overlay->{selection});
} else {
$layer->select();
}
$overlay->update_image;
$layer->open_features_dialog($self, 1);
}
}, $self);
$overlay->signal_connect
( motion_notify => \&show_information, $self );
return $overlay;
}
sub open_history {
my($self, $filename) = @_;
my $history;
if ($filename) {
my $mode = 0600;
chmod $mode, $filename if -e $filename;
if (open TMP, $filename) {
my @history = <TMP>;
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
}
close TMP;
} else {
croak "$!: $self->{resources_file}";
}
}
while ($self->delete_selected(1)) {};
delete $self->{dialogs};
delete $self->{commands};
delete $self->{functions};
$self->{overlay}->close;
delete $self->{overlay};
delete $self->{model};
for my $key ('mode_button', 'geometry_button', 'toolbar', 'tree_view', 'entry', 'statusbar') {
$self->{$key}->destroy;
delete $self->{$key};
}
while (my($key, $widget) = each %$self) {
next if $key eq 'treedumper';
$widget->destroy if blessed($widget) and $widget->isa("Gtk2::Widget");
delete $self->{$key};
}
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
my($self, $message) = @_;
my $dialog = Gtk2::MessageDialog->new(undef,
'destroy-with-parent',
'info',
'close',
$message);
$dialog->signal_connect(response => sub {$_[0]->destroy});
$dialog->show_all;
}
## @fn overlay_menu()
# @brief Construct a menu for an overlay object.
sub overlay_menu {
my @menu =
('Zoom to pre_vious' => sub {
my ($item, $self) = @_;
my $zoom = pop @{$self->{zoom_stack}};
$self->zoom(@$zoom, 0, 1) if $zoom;
},
1 => 0,
'Reselect' => sub {
my ($item, $self) = @_;
$self->signal_emit('new_selection');
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
my $selection = $tree_view->get_selection;
my @rows = $selection->get_selected_rows;
my @res = $tree_view->get_path_at_pos($event->x, $event->y);
return unless defined $res[0];
my $index = $res[0] ? $res[0]->to_string : '';
my $column = $res[1] ? $res[1]->get_title : '';
my $path = Gtk2::TreePath->new($index);
if (@rows < 2) {
$layer = $self->{overlay}->get_layer_by_index($index);
return unless $layer;
} else {
for my $r (@rows) {
$layer = $self->{overlay}->get_layer_by_index($r->to_string);
push @layers, $layer;
}
}
if ($event->button == 3) {
$tree_view->set_cursor($path);
my $hide = $layer->visible() ? '_Hide' : '_Show';
my @items = @layers ?
( '_Hide' => sub {
my($layers, $self) = @{$_[1]};
for my $layer (@$layers) {
$layer->visible(0);
}
$self->update;
$self->{overlay}->render;
},
'_Show' => sub {
my($layers, $self) = @{$_[1]};
for my $layer (@$layers) {
$layer->visible(1);
}
$self->update;
$self->{overlay}->render;
},
'_Remove' => sub {
my($layers, $self) = @{$_[1]};
for my $layer (@$layers) {
$self->{model}->remove($layer->{_tree_index});
$self->{overlay}->remove_layer_by_name($layer->name);
}
$self->{overlay}->render;
}
)
:
(
'_Zoom to' => sub {
my($layer, $self) = @{$_[1]};
$self->{overlay}->zoom_to($layer);
},
'_Up' => sub {
my($layer, $self) = @{$_[1]};
$self->move_up();
},
'_Down' => sub {
my($layer, $self) = @{$_[1]};
$self->move_down();
},
$hide => sub {
my($layer, $self) = @{$_[1]};
$layer->visible(!$layer->visible());
$self->update;
$self->{overlay}->render;
},
'_Remove' => sub {
my($layer, $self) = @{$_[1]};
$self->delete_selected();
}
);
# add items from the layer classes
unless (@layers) {
push @items, ( 1 => 0 );
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
$item->show;
$menu->append($item);
}
$menu->popup(undef, undef, undef, undef, $event->button, $event->time);
return 1;
} elsif ($column =~ /^v/) {
$layer->visible(!$layer->visible());
$self->update;
$self->{overlay}->render;
} elsif ($column =~ /^t/) {
$tree_view->columns_autosize();
}
return 0;
}
## @ignore
sub show_information {
my($overlay, $self) = @_;
my($x, $y) = $overlay->event_pixel2point;
my $layer = $self->get_selected_layer();
my $location = sprintf("(x,y) = (%.4f, %.4f)", $x, $y);
my $value = '';
if ($layer and $layer->isa('Geo::Raster')) {
my @ij = $layer->w2g($x, $y);
$location .= sprintf(", (i,j) = (%i, %i)",@ij);
$value = $layer->point($x, $y);
if (defined $value and $value ne 'nodata' and $layer->{INFO}) {
$value = $layer->{TABLE}->{DATA}->[$value]->[$layer->{INFO}-1];
}
}
$self->{statusbar}->pop(0);
$value = '' unless defined $value;
# additional info, based on mode
my($dim, $val) = $self->{overlay}->rubberband_value();
if (defined $dim) {
$dim = $dim == 1 ? 'length' : 'area';
if (defined $val) {
my $d = '';
if ($val > 1000000) {
$val /= 1000000;
$d = 'M';
} elsif ($val > 1000) {
$val /= 1000;
$d = 'k';
}
$val = sprintf(" $dim = %.2f$d", $val);
} else {
$val = " $dim not computed";
}
} else {
$val = '';
}
my $mode = $self->{overlay}->rubberband_mode();
$self->{statusbar}->push(0, "$mode $location $value$val");
}
## @ignore
sub inspect {
my($self, $data, $name) = @_;
$name = 'unknown variable' unless $name;
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
$self->{model}->set ($layer->{_tree_index},
0, $layer->name(),
1, $type,
2, $visible,
3, $alpha,
);
}
## @method Gtk2::Ex::Geo::Layer add_layer($object, $name, $do_not_zoom_to)
# @brief Add a layer to the overlay and the tree store
#
# The default behavior is to zoom to the new layer. The layer is
# upgraded using the upgrade method of the registered layer classes.
#
# @param object A geospatial data object. Must be either an object of
# a subclass of Gtk2::Ex::Geo::Layer or a data object that is
# recognized by such. It is the responsibility of the upgrade method
# of the layer class to upgrade the data object to a layer object.
# @param name (optional) Name for the new layer.
# @param do_not_zoom_to (optional) Whether to not to zoom the overlay
# to this layer. Forwarded to Gtk2::Ex::Geo::Overlay::add_layer.
# @return
sub add_layer {
my($self, $object, $name, $do_not_zoom_to) = @_;
return unless $object;
my $layer;
for $upgrade (@{$self->{upgrades}}) {
$layer = $upgrade->($object);
last if $layer;
}
if ($layer) {
$layer = $object if $layer == 1; # backwards compatibility
} else {
$layer = $object;
}
return unless $layer->isa('Gtk2::Ex::Geo::Layer');
my $i = $self->{overlay}->index_of_layer($name) if defined $name;
croak "layer with name $name already exists" if defined $i;
$layer->name($name);
$layer->{_tree_index} = $self->{model}->insert (undef, 0);
$self->set_layer($layer);
$self->{overlay}->add_layer($layer, $do_not_zoom_to);
return $layer;
}
## @method Gtk2::Ex::Geo::Layer layer($name)
# @param name
# @return
sub layer {
my($self, $name) = @_;
return $self->{overlay}->get_layer_by_name($name);
}
## @method layers
# @return a list of all layers (not the internal list but a copy)
sub layers {
my($self) = @_;
my @a = @{$self->{overlay}->{layers}};
return @a;
}
## @method get_focal($name)
# @brief Returns a selected (or visible) part of a raster layer by its name.
# @deprecated Selected and clip are implemented elsewhere.
sub get_focal {
my($self, $name) = @_;
my $gd = $self->{overlay}->get_layer_by_name($name);
if ($gd and $gd->isa('Geo::Raster')) {
my @clip = $self->{overlay}->get_focus;
@clip = $gd->wa2ga(@clip);
# do not expand the view
$clip[2]--;
$clip[3]--;
return $gd->clip(@clip);
}
}
## @method update
# @brief Updates the whole layer list.
sub update {
my($self) = @_;
for my $layer (@{$self->{overlay}->{layers}}) {
$self->set_layer($layer);
}
}
## @ignore
sub swap {
my($array,$i1,$i2) = @_;
my $e1 = $array->[$i1];
my $e2 = $array->[$i2];
$array->[$i1] = $e2;
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
}
## @method move_down
# @brief Moves the selected layer down in the list.
sub move_down {
my($self) = @_;
my ($path, $focus_column) = $self->{tree_view}->get_cursor;
return unless $path;
my $index = $path->to_string;
my $n = $#{$self->{overlay}->{layers}};
if ($index < $n) {
my($layer1,$layer2) = swap($self->{overlay}->{layers},$n-$index,$n-$index-1);
$self->{model}->move_after($layer1->{_tree_index},$layer2->{_tree_index});
$self->{overlay}->render;
}
}
## @method move_up
# @brief Moves the selected layer up in the list.
sub move_up {
my($self) = @_;
my ($path, $focus_column) = $self->{tree_view}->get_cursor;
return unless $path;
my $index = $path->to_string;
my $n = $#{$self->{overlay}->{layers}};
if ($index > 0) {
my($layer1,$layer2) = swap($self->{overlay}->{layers},$n-$index,$n-$index+1);
$self->{model}->move_before($layer1->{_tree_index},$layer2->{_tree_index});
$self->{overlay}->render;
}
}
## @method remove_layer
# @brief Removes the selected layer.
# @return Success or failure
sub remove_layer {
my($self, $name, $do_not_render) = @_;
my $layer = $self->{overlay}->get_layer_by_name($name);
return unless $layer;
$self->{model}->remove($layer->{_tree_index});
$self->{overlay}->remove_layer_by_name($name);
delete($self->{focused}) if $self->{focused} and $self->{focused}->name eq $layer->name;
$layer->close($self);
$self->{overlay}->render unless $do_not_render;
return 1;
}
## @method delete_selected
# @brief Removes the selected layer and destroys it.
# @return Success or failure
sub delete_selected {
my($self, $do_not_render) = @_;
my $n = $#{$self->{overlay}->{layers}};
return if $n < 0;
my ($path, $focus_column) = $self->{tree_view}->get_cursor;
return unless $path;
my $index = $path->to_string;
return if $index < 0 or $index > $n;
my($layer) = splice(@{$self->{overlay}->{layers}}, $n-$index, 1);
$self->{model}->remove($layer->{_tree_index});
delete($self->{focused}) if $self->{focused} and $self->{focused}->name eq $layer->name;
$layer->close($self);
if ($n > 0) {
$index-- if $index == $n;
$self->{tree_view}->set_cursor(Gtk2::TreePath->new($index));
}
$self->{overlay}->render unless $do_not_render;
return 1;
}
## @method get_selected
# @brief Returns the selected layer.
sub get_selected_layer {
my($self) = @_;
my($path, $focus_column) = $self->{tree_view}->get_cursor;
return unless $path;
my $index = $path->to_string;
return $self->{overlay}->get_layer_by_index($index);
}
## @method select_layer($name)
# @brief Selects a layer.
sub select_layer {
my($self, $name) = @_;
my $index = $self->{overlay}->index_of_layer($name);
if (defined $index) {
$self->{tree_view}->set_cursor(Gtk2::TreePath->new($index));
}
}
## @ignore
# explain this in some dox file
sub eval_entry {
my($entry, $event, $self) = @_;
my $key = $event->keyval;
lib/Gtk2/Ex/Geo/Glue.pm.in view on Meta::CPAN
if ($function and $self->{functions}{$function}) {
if ($self->{functions}{$function}{sub}) {
$text =~ s/^$function/$self->{functions}{$function}{sub}/;
} else { # object
$text =~ s/^$function/\$self->{functions}{$function}{object}-\>$function/;
}
}
my @g = $text =~ /\$(\w+)/g;
my @_gd;
for my $i (0..$#g) {
$_gd[$i] = $focal ? $self->get_focal($g[$i]) : $self->{overlay}->get_layer_by_name($g[$i]);
next unless $_gd[$i];
$text =~ s/\$$g[$i]\b/\$_gd[$i]/;
}
{
no strict;
eval $text;
croak "$text\n$@" if $@;
}
for my $i (0..$#g) {
if ($self->{overlay}->get_layer_by_name($g[$i])) {
$_gd[$i]->value_range() if $_gd[$i]->isa('Geo::Raster');
} else {
eval "\$self->add_layer(\$$g[$i],'$g[$i]',1);" if $g[$i] and $g[$i] ne 'self';
}
}
undef @_gd;
$self->update();
$self->{overlay}->render;
return 1;
} elsif ($key == $Gtk2::Gdk::Keysyms{Up}) {
$entry->set_text($self->{history}->arrow_up);
return 1;
} elsif ($key == $Gtk2::Gdk::Keysyms{Down}) {
$entry->set_text($self->{history}->arrow_down);
return 1;
}
}
sub render {
$_[0]->{overlay}->render;
}
sub simulate {
my($self, $sub) = @_;
$self->stop;
$self->{_event_source} = Glib::Idle->add($sub);
}
sub stop {
my($self) = @_;
lib/Gtk2/Ex/Geo/Layer.pm view on Meta::CPAN
# @todo add machinery for multiselection.
#
# @return a reference to the items array.
sub menu_items {
my($self) = @_;
my @items;
push @items, (
'_Unselect all' => sub {
my($self, $gui) = @{$_[1]};
$self->select;
$gui->{overlay}->update_image;
$self->open_features_dialog($gui, 1);
},
'_Symbol...' => sub {
my($self, $gui) = @{$_[1]};
$self->open_symbols_dialog($gui);
},
'_Colors...' => sub {
my($self, $gui) = @{$_[1]};
$self->open_colors_dialog($gui);
},
lib/Gtk2/Ex/Geo/Layer.pm view on Meta::CPAN
sub value_range {
return (0, 0);
}
## @method @world()
#
# @brief A callback function. Return the bounding box.
# @return (minx, miny, maxx, maxy)
## @method render($pb, $cr, $overlay, $viewport)
#
# @brief A callback function. Render the layer.
# @param pb Gtk2::Gdk::Pixbuf object
# @param cr Cairo context
# @param overlay Gtk2::Ex::Geo::Overlay object
# @param viewport The pixbuf / cairo surface area in map coordinates
# [minx, miny, maxx, maxy]
## @method render_selection($gc)
#
# @brief Render the selection using the given graphics context
# @param $gc Gtk2::Gdk::GC
sub render_selection {
}
## @method void render($pb, $cr, $overlay, $viewport)
#
# @brief A request to render the data of the layer onto a surface.
#
# @param[in,out] pb A (XS wrapped) pointer to a gtk2_ex_geo_pixbuf.
# @param[in,out] cr A Cairo::Context object for the surface to draw on.
# @param[in] overlay A Gtk2::Ex::Geo::Overlay object which manages the surface.
# @param[in] viewport A reference to the bounding box [min_x, min_y,
# max_x, max_y] of the surface in world coordinates.
sub render {
my($self, $pb, $cr, $overlay, $viewport) = @_;
}
## @method $bootstrap_dialog($gui, $dialog, $title, $connects)
#
# @brief Bootstrap the requested dialog.
#
# The requested dialog is asked from a Glue object, stored into the
# layer, and presented.
#
# @param gui A Gtk2::Ex::Geo::Glue object
lib/Gtk2/Ex/Geo/Overlay.pm view on Meta::CPAN
use Geo::OGC::Geometry;
use vars qw / $EDIT_SNAP_DISTANCE /;
our $VERSION = '0.62'; # same as Geo.pm
=pod
=head1 NAME
Gtk2::Ex::Geo::Overlay - A Gtk2 widget for a visual overlay of geospatial data
The <a href="http://geoinformatics.aalto.fi/doc/Geoinformatica/html/">
documentation of Gtk2::Ex::Geo</a> is written in doxygen format.
=cut
$EDIT_SNAP_DISTANCE = 5;
use Glib::Object::Subclass
Gtk2::ScrolledWindow::,
lib/Gtk2/Ex/Geo/Overlay.pm view on Meta::CPAN
return (round(($p[0] - $self->{minX})/$self->{pixel_size} - 0.5),
round(($self->{maxY} - $p[1])/$self->{pixel_size} - 0.5));
}
package Gtk2::Ex::Geo::Canvas;
our @ISA = qw(Gtk2::Gdk::Pixbuf);
sub new {
my($class, $layers,
$minX, $maxY, $pixel_size, $w_offset, $h_offset,
$width, $height,
$bg_r, $bg_g, $bg_b, $bg_a, $overlay) = @_;
return unless defined $minX;
$overlay = Gtk2::Ex::Geo::PseudoOverlay->new($minX, $maxY, $pixel_size) unless $overlay;
my @viewport = ($minX+$pixel_size*$w_offset, 0, 0, $maxY-$pixel_size*$h_offset);
$viewport[2] = $viewport[0]+$pixel_size*$width;
$viewport[1] = $viewport[3]-$pixel_size*$height;
my $pb = &Gtk2::Ex::Geo::gtk2_ex_geo_pixbuf_create($width, $height,
$viewport[0], $viewport[3],
$pixel_size,
$bg_r, $bg_g, $bg_b, $bg_a);
my $surface = &Gtk2::Ex::Geo::gtk2_ex_geo_pixbuf_get_cairo_surface($pb);
my $cr = Cairo::Context->create($surface);
for my $layer (@$layers) {
$layer->render($pb, $cr, $overlay, \@viewport);
}
undef $cr;
undef $surface;
my $self = &Gtk2::Ex::Geo::gtk2_ex_geo_pixbuf_get_pixbuf($pb);
&Gtk2::Ex::Geo::gtk2_ex_geo_pixbuf_destroy($pb); # does not delete the real pixbuf
bless($self, $class);
}
}
lib/Gtk2/Ex/Geo/Overlay.pm view on Meta::CPAN
$self->{old_vadj} = $self->get_vscrollbar->get_adjustment; # prevents a warning
$self->get_vscrollbar->set_adjustment
(Gtk2::Adjustment->new($self->{offset}[1], 0, $self->{canvas_size}[1], $size->[1]/20,
$size->[1], $size->[1]));
$self->signal_emit ('map-updated');
}
## @method render_geometry($gc, $geom)
# @brief Render a geometry on the overlay.
#
# @note this should be called annotate or made detect the context (gdk vs cairo)
# Call update_image after you are finished with drawing on the pixmap.
# @param gc A gdk graphics context (Gtk2::Gdk::GC object)
# @param geom A Geo::OGC::Geometry object.
sub render_geometry {
my($self, $gc, $geom, %param) = @_;
if ($geom->isa('Geo::OGC::GeometryCollection'))
{
for my $g ($geom->NumGeometries) {
lib/Gtk2/Ex/Geo/Overlay.pm view on Meta::CPAN
{
$self->render_geometry($gc, $geom->ExteriorRing, %param);
for my $i (0..$geom->NumInteriorRing-1) {
$self->render_geometry($gc, $geom->InteriorRingN($i), %param);
}
}
}
## @method update_image($annotations, $user_param)
# @param annotations A subroutine for user annotations. Called like
# this: $annotations->($overlay, $pixmap, $gc, $user_param).
# @param user_param User parameter for the annotations.
# @brief Updates the image on the screen to show the changes in pixmap.
sub update_image {
my($self, $annotations, $user_param) = @_;
return unless $self->{pixbuf};
$self->{image}->set_from_pixbuf(undef);
$self->{pixmap} = $self->{pixbuf}->render_pixmap_and_mask(0);
my $gc = Gtk2::Gdk::GC->new($self->{pixmap});
$self->{pixmap}->draw_line($gc, 0, 0, 0, 0); # strange bug, the first line is not drawn
$self->signal_emit('pixmap_ready');
my $self = Gtk2::Ex::Geo::Layer::new($package);
return $self;
}
sub name {
'test';
}
sub world {
return (0, 0, 100, 100);
}
sub render {
my($self, $pb, $cr, $overlay, $viewport) = @_;
}
}
ok(1);
if (0) {
my($window, $gis) = Gtk2::Ex::Geo::simple(classes => [qw/My::Test::Layer/]);
ok(1);
if ($have_gnuplot) {
package Gtk2::Ex::Geo::Test1;
our @ISA = qw(Gtk2::Ex::Geo::Layer);
sub new {
my $self = Gtk2::Ex::Geo::Layer::new(@_);
return $self;
}
sub world {
return (0, 0, 100, 100);
}
sub render {
my($self, $pb, $cr, $overlay, $viewport) = @_;
}
sub got_focus {
my($self, $gui) = @_;
print STDERR $self->name," got focus\n";
$self->{_tag} = $gui->{overlay}->signal_connect(drawing_changed => \&drawing_changed, $self);
}
sub lost_focus {
my($self, $gui) = @_;
print STDERR $self->name," lost focus\n";
$gui->{overlay}->signal_handler_disconnect($self->{_tag}) if $self->{_tag};
}
sub drawing_changed {
my(undef, $self) = @_;
print STDERR $self->name," was notified of a change in drawing\n";
}
sub select {
my($self, %params) = @_;
for my $k (keys %params) {
print STDERR $self->name," was notified of a change in selection: $k=>$params{$k}\n";
}
package Gtk2::Ex::Geo::Test2;
our @ISA = qw(Gtk2::Ex::Geo::Layer);
sub new {
my $self = Gtk2::Ex::Geo::Layer::new(@_);
return $self;
}
sub world {
return (0, 0, 100, 100);
}
sub render {
my($self, $pb, $cr, $overlay, $viewport) = @_;
}
sub got_focus {
my($self) = @_;
print STDERR $self->name," got focus\n";
}
sub lost_focus {
my($self, $gui) = @_;
print STDERR $self->name," lost focus\n";
}
sub select {
$gis->register_function( name => 'plot', object => $gnuplot );
$gis->register_function( name => 'p', object => $gnuplot );
}
my $layer = Gtk2::Ex::Geo::Test1->new(name => 'test 1');
$gis->add_layer($layer);
$layer = Gtk2::Ex::Geo::Test2->new(name => 'test 2');
$gis->add_layer($layer);
$gis->{overlay}->signal_connect(update_layers =>
sub {
#print STDERR "in callback: @_\n";
});
$gis->register_commands(
[
tag => 'test popup',
label => 'Menu',
tip => 'Press to get a menu',
{
}
# layer list
my $list = Gtk2::ScrolledWindow->new();
$list->set_policy("never", "automatic");
$list->add($gis->{tree_view});
# layer list and the map
my $hbox = Gtk2::HBox->new(FALSE, 0);
$hbox->pack_start($list, FALSE, FALSE, 0);
$hbox->pack_start($gis->{overlay}, TRUE, TRUE, 0);
# the stack
my $vbox = Gtk2::VBox->new(FALSE, 0);
$vbox->pack_start($gis->{toolbar}, FALSE, FALSE, 0);
#$vbox->add($hbox);
$vbox->pack_start($hbox, TRUE, TRUE, 0);
$vbox->pack_start($gis->{entry}, FALSE, FALSE, 0);
$vbox->pack_start($gis->{statusbar}, FALSE, FALSE, 0);
$window->add($vbox);