From dcb3b729c9e35bbb3d05692d3c910a71483b8e13 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Mon, 3 Jun 2024 11:46:56 +1000 Subject: [PATCH 01/13] GUI: rework the load_shapefile argument parsing --- lib/Biodiverse/GUI/Grid.pm | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/Biodiverse/GUI/Grid.pm b/lib/Biodiverse/GUI/Grid.pm index aabe68071..efd955339 100644 --- a/lib/Biodiverse/GUI/Grid.pm +++ b/lib/Biodiverse/GUI/Grid.pm @@ -627,8 +627,11 @@ sub set_overlay { } if ($shapefile) { - my @args = @{ $self->{dataset_info} }; - $self->load_shapefile(@args, $shapefile, $colour); + $self->load_shapefile( + dataset_info => $self->{dataset_info}, + file => $shapefile, + colour => $colour, + ); } return; @@ -649,7 +652,12 @@ EOL } sub load_shapefile { - my ($self, $min_x, $min_y, $max_x, $max_y, $cell_x, $cell_y, $shapefile, $colour) = @_; + my ($self, %args) = @_; + # my ($self, $min_x, $min_y, $max_x, $max_y, $cell_x, $cell_y, $shapefile, $colour) = @_; + my $info = $args{info} // $self->{dataset_info}; + my ($min_x, $min_y, $max_x, $max_y, $cell_x, $cell_y) = @$info; + my $shapefile = $args{file}; + my $colour = $args{colour}; my @rect = ( $min_x - $cell_x, @@ -692,6 +700,7 @@ sub load_shapefile { ); $shapefile_group->raise_to_top(); + # $shapefile_group->lower_to_bottom(); $self->{shapefile_group} = $shapefile_group; # Add all shapes @@ -736,6 +745,7 @@ sub load_shapefile { my $poly = Gnome2::Canvas::Item->new ( $shapefile_group, 'Gnome2::Canvas::Line', + # 'Gnome2::Canvas::Polygon', points => \@plot_points, fill_color_gdk => $colour, ); From cd2db2f1df81cd3a5552d17689da5591d6824cd6 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Mon, 3 Jun 2024 11:47:36 +1000 Subject: [PATCH 02/13] GUI: soften language when missing shapefiles removed from project "Deleted" might make some users believe the files are deleted. --- lib/Biodiverse/GUI/Project.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Biodiverse/GUI/Project.pm b/lib/Biodiverse/GUI/Project.pm index 898ac4607..63a8eae3b 100644 --- a/lib/Biodiverse/GUI/Project.pm +++ b/lib/Biodiverse/GUI/Project.pm @@ -1551,7 +1551,7 @@ sub init_overlay_hash { # Tell user if any missing if ( scalar @missing_overlays > 0 ) { my $text = -"The following overlays are missing and have been deleted from the project:\n"; +"The following overlays are missing and have been removed from the project:\n"; foreach my $name (@missing_overlays) { $text .= " $name\n"; } From 507f6cfe0754f1a434492daddbc5f7ff15c443a6 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Mon, 3 Jun 2024 12:12:21 +1000 Subject: [PATCH 03/13] GUI overlay selector: don't expand colour buttons Previously these became larger as the window was made taller. --- bin/ui/wndOverlays.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/ui/wndOverlays.ui b/bin/ui/wndOverlays.ui index c40e0363e..c90b5d0ab 100644 --- a/bin/ui/wndOverlays.ui +++ b/bin/ui/wndOverlays.ui @@ -90,7 +90,7 @@ - True + False True 2 From 4e1ea1b86df6921e6b691ab52c8d41361cd14866 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Mon, 3 Jun 2024 13:17:45 +1000 Subject: [PATCH 04/13] GUI: Support plotting of shapefiles as polygon Currently defaults to being under the grid cells. --- lib/Biodiverse/GUI/Grid.pm | 31 +++++++++------- lib/Biodiverse/GUI/Overlays.pm | 65 +++++++++++++++++++++++++++------- 2 files changed, 72 insertions(+), 24 deletions(-) diff --git a/lib/Biodiverse/GUI/Grid.pm b/lib/Biodiverse/GUI/Grid.pm index efd955339..f15cf7d8f 100644 --- a/lib/Biodiverse/GUI/Grid.pm +++ b/lib/Biodiverse/GUI/Grid.pm @@ -616,9 +616,8 @@ sub get_base_struct { # Draws a polygonal shapefile sub set_overlay { - my $self = shift; - my $shapefile = shift; - my $colour = shift || OVERLAY_COLOUR; + my ($self, %args) = @_; + # Delete any existing if ($self->{shapefile_group}) { @@ -626,11 +625,11 @@ sub set_overlay { delete $self->{shapefile_group}; } - if ($shapefile) { + if (defined $args{shapefile}) { $self->load_shapefile( + colour => OVERLAY_COLOUR, # default dataset_info => $self->{dataset_info}, - file => $shapefile, - colour => $colour, + %args, ); } @@ -653,11 +652,12 @@ EOL sub load_shapefile { my ($self, %args) = @_; - # my ($self, $min_x, $min_y, $max_x, $max_y, $cell_x, $cell_y, $shapefile, $colour) = @_; + my $info = $args{info} // $self->{dataset_info}; my ($min_x, $min_y, $max_x, $max_y, $cell_x, $cell_y) = @$info; - my $shapefile = $args{file}; + my $shapefile = $args{shapefile}; my $colour = $args{colour}; + my $plot_as_poly = $args{plot_as_poly}; my @rect = ( $min_x - $cell_x, @@ -699,8 +699,16 @@ sub load_shapefile { y => 0, ); - $shapefile_group->raise_to_top(); - # $shapefile_group->lower_to_bottom(); + my $is_polygon = $shapefile->shape_type_text =~ m/polygon/i; + + my $canvas_shape_type = 'Gnome2::Canvas::Line'; + if ($is_polygon && $plot_as_poly) { + $canvas_shape_type = 'Gnome2::Canvas::Polygon'; + $shapefile_group->lower_to_bottom(); + } + else { + $shapefile_group->raise_to_top(); + } $self->{shapefile_group} = $shapefile_group; # Add all shapes @@ -744,8 +752,7 @@ sub load_shapefile { if (@plot_points > 2) { # must have more than one point (two coords) my $poly = Gnome2::Canvas::Item->new ( $shapefile_group, - 'Gnome2::Canvas::Line', - # 'Gnome2::Canvas::Polygon', + $canvas_shape_type, points => \@plot_points, fill_color_gdk => $colour, ); diff --git a/lib/Biodiverse/GUI/Overlays.pm b/lib/Biodiverse/GUI/Overlays.pm index 1046d2c5a..224260c3a 100644 --- a/lib/Biodiverse/GUI/Overlays.pm +++ b/lib/Biodiverse/GUI/Overlays.pm @@ -14,6 +14,9 @@ use Biodiverse::GUI::Project; my $default_colour = Gtk2::Gdk::Color->parse('#001169'); my $last_selected_colour = $default_colour; +use constant COL_FNAME => 0; +use constant COL_PLOT_POLY => 1; + sub show_dialog { my $grid = shift; @@ -70,12 +73,22 @@ sub init_overlay_list { my $tree = $dlgxml->get_object('treeOverlays'); my $col_name = Gtk2::TreeViewColumn->new(); - my $name_renderer = Gtk2::CellRendererText->new(); - $col_name->set_title('Filename'); + my $name_renderer = Gtk2::CellRendererText->new (); + $col_name->set_title('File name'); $col_name->pack_start($name_renderer, 1); $col_name->add_attribute($name_renderer, text => 0); $tree->insert_column($col_name, -1); + my $col_plot_poly = Gtk2::TreeViewColumn->new(); + $col_plot_poly->set_title('Plot as polygon'); + my $poly_renderer = Gtk2::CellRendererToggle->new(); + $col_plot_poly->pack_start($poly_renderer, 0); + $poly_renderer->signal_connect('toggled' => \&_plot_poly_toggled, $model); + $col_plot_poly->set_attributes($poly_renderer, + 'active' => 1, + ); + $tree->insert_column($col_plot_poly, -1); + # fiddling around with colour selection #my $colColour = Gtk2::TreeViewColumn->new(); #my $colour_button = Gtk2::CellRendererPixbuf->new(); @@ -84,25 +97,39 @@ sub init_overlay_list { #$colColour->add_attribute($colour_button, text => 0); #$tree->insert_column($colColour, -1); - $tree->set_headers_visible(0); + $tree->set_headers_visible(1); $tree->set_model($model); return $tree; } +sub _plot_poly_toggled { + my ($cell, $path_str, $model) = @_; + + my $path = Gtk2::TreePath->new_from_string ($path_str); + + # get toggled iter + my $iter = $model->get_iter ($path); + my ($bool) = $model->get ($iter, COL_PLOT_POLY); + + # toggle the value + $model->set ($iter, COL_PLOT_POLY, !$bool); +} + # Make the object tree that appears on the left sub make_overlay_model { + my $project = shift; + my $model = Gtk2::ListStore->new( 'Glib::String', - #'Glib::Boolean', # fiddling around with colour selection + 'Glib::Boolean', ); - my $project = shift; my $overlays = $project->get_overlay_list(); foreach my $name (@{$overlays}) { my $iter = $model->append; - $model->set($iter, 0, $name); + $model->set($iter, 0, $name, 1, 1); } @@ -120,9 +147,10 @@ sub get_selection { return if not $path; my $iter = $model->get_iter($path); - my $name = $model->get($iter, 0); + my $name = $model->get($iter, COL_FNAME); + my $plot_as_poly = $model->get($iter, COL_PLOT_POLY); - return wantarray ? ($name, $iter) : $name; + return wantarray ? ($iter, $name, $plot_as_poly) : $name; } @@ -164,7 +192,7 @@ sub on_add { if (!_shp_type_is_point($filename)) { my $iter = $list->get_model->append; - $list->get_model->set($iter, 0, $filename); + $list->get_model->set($iter, COL_FNAME, $filename); my $sel = $list->get_selection; $sel->select_iter($iter); @@ -193,12 +221,21 @@ sub _shp_type_is_point { return $type =~/point/i; } +sub _shp_type_is_polygon { + my $name = shift; + + my $shpfile = Geo::ShapeFile->new ($name); + my $type = $shpfile->shape_type_text; + + return $type =~/polygon/i; +} + sub on_delete { my $button = shift; my $args = shift; my ($list, $project) = @$args; - my ($filename, $iter) = get_selection($list); + my ($iter, $filename) = get_selection($list); return if not $filename; $project->delete_overlay($filename); $list->get_model->remove($iter); @@ -223,7 +260,7 @@ sub on_set { my $args = shift; my ($list, $project, $grid, $dlg, $colour_button) = @$args; - my $filename = get_selection($list); + my ($iter, $filename, $plot_as_poly) = get_selection($list); my $colour = $colour_button->get_color; @@ -232,7 +269,11 @@ sub on_set { return if not $filename; print "[Overlay] Setting overlay to $filename\n"; - $grid->set_overlay( $project->get_overlay($filename), $colour ); + $grid->set_overlay( + shapefile => $project->get_overlay($filename), + colour => $colour, + plot_as_poly => $plot_as_poly, + ); #$dlg->destroy(); $last_selected_colour = $colour; From 2889a4cc0001f6d51fcf9ef6a11951b0b5b2987a Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Mon, 3 Jun 2024 13:57:17 +1000 Subject: [PATCH 05/13] GUI overlays: name button Remove instead of Delete "Deleted" might make some users believe the files are deleted. Similar to a previous change. --- bin/ui/wndOverlays.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/ui/wndOverlays.ui b/bin/ui/wndOverlays.ui index c90b5d0ab..d0b10fb42 100644 --- a/bin/ui/wndOverlays.ui +++ b/bin/ui/wndOverlays.ui @@ -121,13 +121,13 @@ - gtk-delete + Remove True True True True True - Delete selected file from the list + Remove selected entry from the list True From e050dbe05728582595867a98109b7623654e0565 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Mon, 3 Jun 2024 13:59:23 +1000 Subject: [PATCH 06/13] GUI: more refined removal of overlays Previously we were deleting objects that were still needed. This could occur when a file was loaded more than once. The system simply reloaded in such cases but this avoids doing that extra work. --- lib/Biodiverse/GUI/Overlays.pm | 10 ++++++---- lib/Biodiverse/GUI/Project.pm | 21 ++++++++++++--------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/lib/Biodiverse/GUI/Overlays.pm b/lib/Biodiverse/GUI/Overlays.pm index 224260c3a..b86e30f0a 100644 --- a/lib/Biodiverse/GUI/Overlays.pm +++ b/lib/Biodiverse/GUI/Overlays.pm @@ -16,6 +16,7 @@ my $last_selected_colour = $default_colour; use constant COL_FNAME => 0; use constant COL_PLOT_POLY => 1; +use constant COL_COLOUR => 1; sub show_dialog { my $grid = shift; @@ -149,8 +150,9 @@ sub get_selection { my $iter = $model->get_iter($path); my $name = $model->get($iter, COL_FNAME); my $plot_as_poly = $model->get($iter, COL_PLOT_POLY); + my $array_iter = $path->to_string; # only works for a simple tree - return wantarray ? ($iter, $name, $plot_as_poly) : $name; + return wantarray ? ($iter, $name, $plot_as_poly, $array_iter) : $name; } @@ -235,9 +237,9 @@ sub on_delete { my $args = shift; my ($list, $project) = @$args; - my ($iter, $filename) = get_selection($list); - return if not $filename; - $project->delete_overlay($filename); + my ($iter, $filename, undef, $array_iter) = get_selection($list); + return if not defined $filename; + $project->delete_overlay($filename, $array_iter); $list->get_model->remove($iter); return; diff --git a/lib/Biodiverse/GUI/Project.pm b/lib/Biodiverse/GUI/Project.pm index 63a8eae3b..8d7041152 100644 --- a/lib/Biodiverse/GUI/Project.pm +++ b/lib/Biodiverse/GUI/Project.pm @@ -1499,17 +1499,20 @@ sub get_overlay { sub delete_overlay { my $self = shift; my $name = shift; + my $array_iter = shift; - # Remove from list - foreach my $i ( 0 .. $#{ $self->{OVERLAYS} } ) { - if ( $self->{OVERLAYS}[$i] eq $name ) { - splice( @{ $self->{OVERLAYS} }, $i, 1 ); - last; - } - } + my $overlays = $self->{OVERLAYS}; - # remove from hash - delete $self->{overlay_objects}{$name}; + # Remove from list unless not found or possible + $array_iter //= List::Util::first {$_ eq $name} @$overlays; + return if $array_iter < 0 || $array_iter > $#$overlays; + + splice( @$overlays, $array_iter, 1 ); + + # remove from hash if no longer needed + if (!grep {$_ eq $name} @$overlays) { + delete $self->{overlay_objects}{$name}; + } return; } From e0a78e469ce79a9eee9c80000ecc0de3861ff425 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Mon, 3 Jun 2024 14:18:18 +1000 Subject: [PATCH 07/13] GUI overlays: rename some methods for clarity --- lib/Biodiverse/GUI/Overlays.pm | 6 +++--- lib/Biodiverse/GUI/Project.pm | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Biodiverse/GUI/Overlays.pm b/lib/Biodiverse/GUI/Overlays.pm index b86e30f0a..62886ee56 100644 --- a/lib/Biodiverse/GUI/Overlays.pm +++ b/lib/Biodiverse/GUI/Overlays.pm @@ -16,7 +16,7 @@ my $last_selected_colour = $default_colour; use constant COL_FNAME => 0; use constant COL_PLOT_POLY => 1; -use constant COL_COLOUR => 1; +# use constant COL_COLOUR => 2; sub show_dialog { my $grid = shift; @@ -130,7 +130,7 @@ sub make_overlay_model { foreach my $name (@{$overlays}) { my $iter = $model->append; - $model->set($iter, 0, $name, 1, 1); + $model->set($iter, COL_FNAME, $name, COL_PLOT_POLY, 0); } @@ -272,7 +272,7 @@ sub on_set { print "[Overlay] Setting overlay to $filename\n"; $grid->set_overlay( - shapefile => $project->get_overlay($filename), + shapefile => $project->get_overlay_shape_object($filename), colour => $colour, plot_as_poly => $plot_as_poly, ); diff --git a/lib/Biodiverse/GUI/Project.pm b/lib/Biodiverse/GUI/Project.pm index 8d7041152..7be976542 100644 --- a/lib/Biodiverse/GUI/Project.pm +++ b/lib/Biodiverse/GUI/Project.pm @@ -1477,7 +1477,7 @@ sub get_overlay_list { return $self->{OVERLAYS}; } -sub get_overlay { +sub get_overlay_shape_object { my $self = shift; my $name = shift; From 0a42cecdaa064ea38b1a3d2e4554a1c0ccc834a3 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Mon, 3 Jun 2024 15:11:45 +1000 Subject: [PATCH 08/13] GUI: show/hide the overlay dialog instead of rebuilding each time This simplifies the attribute handing. --- lib/Biodiverse/GUI/GUIManager.pm | 1 + lib/Biodiverse/GUI/Overlays.pm | 43 +++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/lib/Biodiverse/GUI/GUIManager.pm b/lib/Biodiverse/GUI/GUIManager.pm index 872fa67ad..944086737 100644 --- a/lib/Biodiverse/GUI/GUIManager.pm +++ b/lib/Biodiverse/GUI/GUIManager.pm @@ -61,6 +61,7 @@ BEGIN { gladexml => undef, # Main window widgets tabs => [], # Stores refs to Tabs objects. In order of page index. progress_bars => undef, + overlay_components => undef, test_val => '' }; bless $singleton, 'Biodiverse::GUI::GUIManager'; diff --git a/lib/Biodiverse/GUI/Overlays.pm b/lib/Biodiverse/GUI/Overlays.pm index 62886ee56..03be20faf 100644 --- a/lib/Biodiverse/GUI/Overlays.pm +++ b/lib/Biodiverse/GUI/Overlays.pm @@ -5,6 +5,7 @@ use warnings; use Gtk2; #use Data::Dumper; use Geo::ShapeFile; +use Ref::Util qw/is_hashref/; our $VERSION = '4.99_002'; @@ -23,11 +24,26 @@ sub show_dialog { # Create dialog my $gui = Biodiverse::GUI::GUIManager->instance; + my $overlay_components = $gui->{overlay_components}; + + if ($overlay_components) { + my $dlg = $overlay_components->{dialog}; + my $colour_button = $overlay_components->{colour_button}; + $colour_button->set_color($last_selected_colour); + $dlg->show_all; + return; + } + my $dlgxml = Gtk2::Builder->new(); $dlgxml->add_from_file($gui->get_gtk_ui_file('wndOverlays.ui')); my $dlg = $dlgxml->get_object('wndOverlays'); my $colour_button = $dlgxml->get_object('colorbutton_overlays'); - $dlg->set_transient_for( $gui->get_object('wndMain') ); + $dlg->set_transient_for($gui->get_object('wndMain')); + + $gui->{overlay_components} = { + dialog => $dlg, + colour_button => $colour_button, + }; $colour_button->set_color($last_selected_colour); @@ -128,12 +144,21 @@ sub make_overlay_model { my $overlays = $project->get_overlay_list(); - foreach my $name (@{$overlays}) { + foreach my $entry (@{$overlays}) { my $iter = $model->append; - $model->set($iter, COL_FNAME, $name, COL_PLOT_POLY, 0); + if (!is_hashref $entry) { # previous versions did not store these + $entry = { + name => $entry, + plot_as_poly => 0, + }; + } + $model->set( + $iter, + COL_FNAME, $entry->{name}, + COL_PLOT_POLY, $entry->{plot_as_poly} + ); } - return $model; } @@ -194,11 +219,11 @@ sub on_add { if (!_shp_type_is_point($filename)) { my $iter = $list->get_model->append; - $list->get_model->set($iter, COL_FNAME, $filename); + $list->get_model->set($iter, COL_FNAME, $filename, COL_PLOT_POLY, 0); my $sel = $list->get_selection; $sel->select_iter($iter); - $project->add_overlay($filename); + $project->add_overlay({name => $filename}); } else { # warn about points - one day we will fix this my $error = "Selected shapefile is a point type."; @@ -252,7 +277,7 @@ sub on_clear { my ($list, $project, $grid, $dlg) = @$args; $grid->set_overlay(undef); - $dlg->destroy(); + $dlg->hide(); return; } @@ -266,7 +291,7 @@ sub on_set { my $colour = $colour_button->get_color; - $dlg->destroy; + $dlg->hide; return if not $filename; @@ -287,7 +312,7 @@ sub on_cancel { my $button = shift; my $dlg = shift; - $dlg->destroy; + $dlg->hide; return; } From f1345f032ec7125f6366a5707ff87948c9cc696d Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Mon, 3 Jun 2024 15:30:47 +1000 Subject: [PATCH 09/13] GUI overlays: handle new hash structure --- lib/Biodiverse/GUI/Project.pm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/Biodiverse/GUI/Project.pm b/lib/Biodiverse/GUI/Project.pm index 7be976542..124563862 100644 --- a/lib/Biodiverse/GUI/Project.pm +++ b/lib/Biodiverse/GUI/Project.pm @@ -1519,10 +1519,10 @@ sub delete_overlay { sub add_overlay { my $self = shift; - my $name = shift; + my $entry = shift; - $self->{overlay_objects}{$name} = undef; - push @{ $self->{OVERLAYS} }, $name; + $self->{overlay_objects}{$entry->{name}} = undef; + push @{ $self->{OVERLAYS} }, $entry; return; } @@ -1534,13 +1534,14 @@ sub init_overlay_hash { my $existing_overlays = []; my @missing_overlays; - foreach my $name ( @{ $self->{OVERLAYS} } ) { + foreach my $entry ( @{ $self->{OVERLAYS} } ) { + my $name = is_hashref $entry ? $entry->{name} : $entry; if ( Biodiverse::Common->file_is_readable (file_name => $name) ) { # Set hash entry to undef - will load on demand $self->{overlay_objects}{$name} = undef; - push @$existing_overlays, $name; + push @$existing_overlays, $entry; } else { print "[Project] Missing overlay: $name\n"; From 2ba6777be9b99f47bbd87f41c32c95793bbab032 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Mon, 3 Jun 2024 15:31:36 +1000 Subject: [PATCH 10/13] GUI overlays: use methods to access components --- lib/Biodiverse/GUI/GUIManager.pm | 10 ++++++++++ lib/Biodiverse/GUI/Overlays.pm | 8 ++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/Biodiverse/GUI/GUIManager.pm b/lib/Biodiverse/GUI/GUIManager.pm index 944086737..e393ec6b5 100644 --- a/lib/Biodiverse/GUI/GUIManager.pm +++ b/lib/Biodiverse/GUI/GUIManager.pm @@ -332,6 +332,16 @@ sub show_progress { } } +sub get_overlay_components { + my ($self) = @_; + return $self->{overlay_components}; +} + +sub set_overlay_components { + my ($self, $components) = @_; + $self->{overlay_components} = $components; +} + ########################################################## # Initialisation ########################################################## diff --git a/lib/Biodiverse/GUI/Overlays.pm b/lib/Biodiverse/GUI/Overlays.pm index 03be20faf..c30eea366 100644 --- a/lib/Biodiverse/GUI/Overlays.pm +++ b/lib/Biodiverse/GUI/Overlays.pm @@ -24,7 +24,7 @@ sub show_dialog { # Create dialog my $gui = Biodiverse::GUI::GUIManager->instance; - my $overlay_components = $gui->{overlay_components}; + my $overlay_components = $gui->get_overlay_components; if ($overlay_components) { my $dlg = $overlay_components->{dialog}; @@ -40,10 +40,10 @@ sub show_dialog { my $colour_button = $dlgxml->get_object('colorbutton_overlays'); $dlg->set_transient_for($gui->get_object('wndMain')); - $gui->{overlay_components} = { + $gui->set_overlay_components ({ dialog => $dlg, colour_button => $colour_button, - }; + }); $colour_button->set_color($last_selected_colour); @@ -276,7 +276,7 @@ sub on_clear { my $args = shift; my ($list, $project, $grid, $dlg) = @$args; - $grid->set_overlay(undef); + $grid->set_overlay(); $dlg->hide(); return; From 17ce982c7d64f09d3bd58f728de61d58486f53b7 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Mon, 3 Jun 2024 16:08:11 +1000 Subject: [PATCH 11/13] GUI overlays: get_selection returns a hash in list context This simplifies later expansion of returned values. --- lib/Biodiverse/GUI/Overlays.pm | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/Biodiverse/GUI/Overlays.pm b/lib/Biodiverse/GUI/Overlays.pm index c30eea366..5c1972ade 100644 --- a/lib/Biodiverse/GUI/Overlays.pm +++ b/lib/Biodiverse/GUI/Overlays.pm @@ -1,5 +1,6 @@ package Biodiverse::GUI::Overlays; +use 5.010; use strict; use warnings; use Gtk2; @@ -91,6 +92,7 @@ sub init_overlay_list { my $col_name = Gtk2::TreeViewColumn->new(); my $name_renderer = Gtk2::CellRendererText->new (); + #$name_renderer->signal_connect('toggled' => \&_update_colour_for_selection, $model); $col_name->set_title('File name'); $col_name->pack_start($name_renderer, 1); $col_name->add_attribute($name_renderer, text => 0); @@ -133,6 +135,19 @@ sub _plot_poly_toggled { $model->set ($iter, COL_PLOT_POLY, !$bool); } +# sub _update_colour_for_selection { +# my ($cell, $path_str, $model) = @_; +# +# my $path = Gtk2::TreePath->new_from_string ($path_str); +# +# # get toggled iter +# my $iter = $model->get_iter ($path); +# my $colour = $model->get ($iter, COL_PLOT_COLOUR); +# +# # toggle the value +# $model->set ($iter, COL_PLOT_POLY, !$bool); +# } + # Make the object tree that appears on the left sub make_overlay_model { my $project = shift; @@ -177,7 +192,9 @@ sub get_selection { my $plot_as_poly = $model->get($iter, COL_PLOT_POLY); my $array_iter = $path->to_string; # only works for a simple tree - return wantarray ? ($iter, $name, $plot_as_poly, $array_iter) : $name; + return wantarray + ? (iter => $iter, filename => $name, plot_as_poly => $plot_as_poly, array_iter => $array_iter) + : $name; } @@ -262,7 +279,9 @@ sub on_delete { my $args = shift; my ($list, $project) = @$args; - my ($iter, $filename, undef, $array_iter) = get_selection($list); + # my ($iter, $filename, undef, $array_iter) = get_selection($list); + my %results = get_selection($list); + my ($iter, $filename, $array_iter) = @results{qw/iter filename array_iter/}; return if not defined $filename; $project->delete_overlay($filename, $array_iter); $list->get_model->remove($iter); @@ -287,7 +306,10 @@ sub on_set { my $args = shift; my ($list, $project, $grid, $dlg, $colour_button) = @$args; - my ($iter, $filename, $plot_as_poly) = get_selection($list); + # my ($iter, $filename, $plot_as_poly, $array_iter) = get_selection($list); + my %results = get_selection($list); + my ($iter, $filename, $plot_as_poly, $array_iter) + = @results{qw /iter filename plot_as_poly array_iter/}; my $colour = $colour_button->get_color; From 18b3413d7d74f12c4ceec9455b55a766251e373e Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Tue, 4 Jun 2024 09:40:20 +1000 Subject: [PATCH 12/13] GUI overlays: attempt at per-layer colours, currently disabled --- lib/Biodiverse/GUI/Overlays.pm | 97 +++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 25 deletions(-) diff --git a/lib/Biodiverse/GUI/Overlays.pm b/lib/Biodiverse/GUI/Overlays.pm index 5c1972ade..d383217eb 100644 --- a/lib/Biodiverse/GUI/Overlays.pm +++ b/lib/Biodiverse/GUI/Overlays.pm @@ -16,9 +16,10 @@ use Biodiverse::GUI::Project; my $default_colour = Gtk2::Gdk::Color->parse('#001169'); my $last_selected_colour = $default_colour; -use constant COL_FNAME => 0; -use constant COL_PLOT_POLY => 1; -# use constant COL_COLOUR => 2; +use constant COL_FNAME => 0; +use constant COL_PLOT_POLY => 1; +use constant COL_PLOT_COLOUR => 2; +use constant COL_PLOT_COLOUR_BK => 3; sub show_dialog { my $grid = shift; @@ -95,7 +96,7 @@ sub init_overlay_list { #$name_renderer->signal_connect('toggled' => \&_update_colour_for_selection, $model); $col_name->set_title('File name'); $col_name->pack_start($name_renderer, 1); - $col_name->add_attribute($name_renderer, text => 0); + $col_name->add_attribute($name_renderer, text => COL_FNAME); $tree->insert_column($col_name, -1); my $col_plot_poly = Gtk2::TreeViewColumn->new(); @@ -108,13 +109,24 @@ sub init_overlay_list { ); $tree->insert_column($col_plot_poly, -1); - # fiddling around with colour selection - #my $colColour = Gtk2::TreeViewColumn->new(); - #my $colour_button = Gtk2::CellRendererPixbuf->new(); - #$colColour->set_title('Colour'); - #$colColour->pack_start($colour_button, 1); - #$colColour->add_attribute($colour_button, text => 0); - #$tree->insert_column($colColour, -1); + # my $col_colour = Gtk2::TreeViewColumn->new(); + # my $colour_renderer_toggle = Gtk2::CellRendererToggle->new(); + # my $colour_renderer_text = Gtk2::CellRendererText->new(); + # $col_colour->set_title('Colour'); + # $col_colour->pack_start($colour_renderer_toggle, 0); + # $col_colour->pack_start($colour_renderer_text, 0); + # $col_colour->add_attribute($colour_renderer_toggle, active => COL_PLOT_COLOUR); + # $col_colour->set_attributes($colour_renderer_toggle, active => 1); + # $col_colour->add_attribute($colour_renderer_text, + # 'cell-background' => COL_PLOT_COLOUR_BK, + # ); + # $col_colour->set_attributes($colour_renderer_text, + # 'cell-background' => COL_PLOT_COLOUR_BK, + # ); + # $colour_renderer_toggle->signal_connect( + # 'toggled' => \&_update_colour_for_selection, $model + # ); + # $tree->insert_column($col_colour, -1); $tree->set_headers_visible(1); $tree->set_model($model); @@ -135,18 +147,45 @@ sub _plot_poly_toggled { $model->set ($iter, COL_PLOT_POLY, !$bool); } -# sub _update_colour_for_selection { -# my ($cell, $path_str, $model) = @_; -# -# my $path = Gtk2::TreePath->new_from_string ($path_str); -# -# # get toggled iter -# my $iter = $model->get_iter ($path); -# my $colour = $model->get ($iter, COL_PLOT_COLOUR); -# -# # toggle the value -# $model->set ($iter, COL_PLOT_POLY, !$bool); -# } +sub _update_colour_for_selection { + my ($cell, $path_str, $model) = @_; + + my $path = Gtk2::TreePath->new_from_string ($path_str); + + # get toggled iter + my $iter = $model->get_iter ($path); + my ($bool) = $model->get ($iter, COL_PLOT_COLOUR); + + my $gui = Biodiverse::GUI::GUIManager->instance; + my $overlay_components = $gui->get_overlay_components; + my $colour_button = $overlay_components->{colour_button}; + + my $colour = $model->get ($iter, COL_PLOT_COLOUR_BK); + if (!defined $colour or $colour eq 'undef') { + $colour = $colour_button->get_colour; #$self->get_last_colour; + } + + if (!Scalar::Util::blessed $colour) { + $colour = Gtk2::Gdk::Color->parse($colour); + } + $colour_button->set_color($colour); + + $colour_button->clicked; + $colour = $colour_button->get_color; + + say STDERR $bool, ' ', $colour->to_string; + + # toggle the value + $model->set ($iter, + COL_PLOT_COLOUR, !$bool, + ); + $model->set ($iter, + COL_PLOT_COLOUR_BK, $colour->to_string, + # 'cell-background' => $colour->to_string, + ); + say '--- ' . $model->get ($iter, COL_PLOT_COLOUR); + say '--- ' . $model->get ($iter, COL_PLOT_COLOUR_BK); +} # Make the object tree that appears on the left sub make_overlay_model { @@ -155,6 +194,8 @@ sub make_overlay_model { my $model = Gtk2::ListStore->new( 'Glib::String', 'Glib::Boolean', + # 'Glib::Boolean', # next two are colour stuff + # 'Glib::String', ); my $overlays = $project->get_overlay_list(); @@ -165,12 +206,18 @@ sub make_overlay_model { $entry = { name => $entry, plot_as_poly => 0, + # has_colour => undef, + # colour => undef, }; } + # use DDP; + # p $entry; $model->set( $iter, - COL_FNAME, $entry->{name}, - COL_PLOT_POLY, $entry->{plot_as_poly} + COL_FNAME, $entry->{name}, + COL_PLOT_POLY, $entry->{plot_as_poly}, + # COL_PLOT_COLOUR, !!$entry->{colour}, + # COL_PLOT_COLOUR_BK, ($entry->{colour} // 'white'), ); } From a68f4887daba75dc59c1fb6acbd0888c74fc7383 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Tue, 4 Jun 2024 12:10:18 +1000 Subject: [PATCH 13/13] GUI overlays: ensure the overlay dialogue only links to the current grid Otherwise we trigger replots across all open tabs, which currently is not what we want. --- lib/Biodiverse/GUI/Overlays.pm | 88 ++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 24 deletions(-) diff --git a/lib/Biodiverse/GUI/Overlays.pm b/lib/Biodiverse/GUI/Overlays.pm index d383217eb..4f592405d 100644 --- a/lib/Biodiverse/GUI/Overlays.pm +++ b/lib/Biodiverse/GUI/Overlays.pm @@ -27,11 +27,19 @@ sub show_dialog { # Create dialog my $gui = Biodiverse::GUI::GUIManager->instance; my $overlay_components = $gui->get_overlay_components; + my $project = $gui->get_project; if ($overlay_components) { - my $dlg = $overlay_components->{dialog}; + my $dlg = $overlay_components->{dialog}; my $colour_button = $overlay_components->{colour_button}; $colour_button->set_color($last_selected_colour); + + set_button_actions ( + project => $project, + grid => $grid, + %$overlay_components, + ); + $dlg->show_all; return; } @@ -42,48 +50,80 @@ sub show_dialog { my $colour_button = $dlgxml->get_object('colorbutton_overlays'); $dlg->set_transient_for($gui->get_object('wndMain')); - $gui->set_overlay_components ({ - dialog => $dlg, - colour_button => $colour_button, - }); - $colour_button->set_color($last_selected_colour); - my $project = $gui->get_project; my $model = make_overlay_model($project); my $list = init_overlay_list($dlgxml, $model); + my %buttons = map {$_ => $dlgxml->get_object($_)} + (qw /btnAdd btnDelete btnClear btnSet btnOverlayCancel btn_overlay_set_default_colour/); + my %components = ( + dialog => $dlg, + colour_button => $colour_button, + list => $list, + buttons => \%buttons, + ); + + my $signals = set_button_actions ( + %components, + project => $project, + grid => $grid, + ); + + # store some but not all components we set actions for + $gui->set_overlay_components ({ + %components, + signals => $signals, + }); + + $dlg->set_modal(1); + $dlg->show_all(); + + return; +} + +sub set_button_actions { + my %args = @_; + my ($list, $project, $grid, $dlg, $colour_button) + = @args{qw /list project grid dialog colour_button/}; + + my $buttons = $args{buttons}; + my $signals = $args{signals} // {}; # Connect buttons - $dlgxml->get_object('btnAdd')->signal_connect( + + # these are always the same + $signals->{btnAdd} //= $buttons->{btnAdd}->signal_connect( clicked => \&on_add, [$list, $project], ); - $dlgxml->get_object('btnDelete')->signal_connect( + $signals->{btnDelete} //= $buttons->{btnDelete}->signal_connect( clicked => \&on_delete, [$list, $project], ); - $dlgxml->get_object('btnClear')->signal_connect( - clicked => \&on_clear, - [$list, $project, $grid, $dlg], - ); - $dlgxml->get_object('btnSet')->signal_connect( - clicked => \&on_set, - [$list, $project, $grid, $dlg, $colour_button], - ); - $dlgxml->get_object('btnOverlayCancel')->signal_connect( + $signals->{btnOverlayCancel} //= $buttons->{btnOverlayCancel}->signal_connect( clicked => \&on_cancel, $dlg, ); - $dlgxml->get_object('btn_overlay_set_default_colour')->signal_connect( + $signals->{btn_overlay_set_default_colour} + //= $buttons->{btn_overlay_set_default_colour}->signal_connect( clicked => \&on_set_default_colour, $colour_button, ); - - $dlg->set_modal(1); - $dlg->show_all(); - - return; + # these vary by grid so need to be disconnected first or we mess up other plots + foreach my $btn (qw/btnClear btnSet/) { + my $id = $signals->{$btn} // next; + $buttons->{$btn}->signal_handler_disconnect($id); + } + $signals->{btnClear} = $buttons->{btnClear}->signal_connect( + clicked => \&on_clear, + [$list, $project, $grid, $dlg], + ); + $signals->{btnSet} = $buttons->{btnSet}->signal_connect( + clicked => \&on_set, + [$list, $project, $grid, $dlg, $colour_button], + ); + return $signals; } sub init_overlay_list {