# Copyright 2007, 2008, 2009, 2010, 2011 Kevin Ryde # This file is part of Chart. # # Chart is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 3, or (at your option) any later # version. # # Chart is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License along # with Chart. If not, see . package App::Chart::Gtk2::Ex::TreePath::Circular; use 5.008; use strict; use warnings; use Carp; use List::Util qw(min max); use Gtk2; use App::Chart::Gtk2::Ex::TreePath::Subclass; our @ISA = ('App::Chart::Gtk2::Ex::TreePath::Subclass', 'Gtk2::TreePath'); use constant DEBUG => 0; sub goto_index { my ($self, $index) = @_; $self->up; $self->append_index ($index || 0); } sub next { my ($self, $model) = @_; if (! $model) { croak "TreePath::Circular next needs the tree model"; } $self->SUPER::next; my ($cur_index) = $self->get_indices; my $rows = $model->iter_n_children (undef); if ($cur_index >= $rows) { $self->goto_index (0); } } sub prev { my ($self, $model) = @_; if (! $model) { croak "TreePath::Circular next needs the tree model"; } if (! $self->SUPER::prev) { # was at position 0, wrap to end $self->goto_index (max (0, $model->iter_n_children (undef) - 1)); } } sub row_inserted { my ($self, $model, $ins_path, $ins_iter) = @_; my ($cur_index) = $self->get_indices; my ($ins_index) = $ins_path->get_indices; # if inserted before current then advance if ($ins_index < $cur_index) { $self->next ($model); } if (DEBUG) { print "ins to ", $self->to_string, "\n"; } } sub row_deleted { my ($self, $model, $del_path) = @_; my ($del_index) = $del_path->get_indices; my ($cur_index) = $self->get_indices; # if deleted before current then decrement if ($del_index < $cur_index) { $self->prev ($model); } if (DEBUG) { print "del to ", $self->to_string, "\n"; } } sub rows_reordered { my ($self, $model, $reordered_path, $reordered_iter, $aref) = @_; my ($cur_index) = $self->get_indices; # follow to new index $self->goto_index ($aref->[$cur_index]); if (DEBUG) { print "reorder to ", $self->to_string, "\n"; } } 1; __END__ =head1 NAME App::Chart::Gtk2::Ex::TreePath::Circular -- managed path position with wraparound =for test_synopsis my ($model) =head1 SYNOPSIS use App::Chart::Gtk2::Ex::TreePath::Circular; my $path = My::TreePath::Circular->new; $path->next ($model); $path->prev ($model); =head1 CLASS HIERARCHY C is a Perl subclass of C, Glib::Boxed Gtk2::TreePath App::Chart::Gtk2::Ex::TreePath::Circular =head1 DESCRIPTION C is a version of C designed to maintain a position in the model's row data and to wrap round from the end back to the beginning of the rows when necessary. It's used for instance by C to maintain the current item position in that display. =head1 FUNCTIONS =over 4 =item C<< App::Chart::Gtk2::Ex::TreePath::Circular->new >> Create and return a new path object. =item C<< App::Chart::Gtk2::Ex::TreePath::Circular->new_first >> Create and return a new path object positioned at index 0, ie. the start of any model's data. =item C<< App::Chart::Gtk2::Ex::TreePath::Circular->new_from_indices ($index) >> Create and return a new path object positioned at the given index. Index 0 is the first in any model. =item C<< App::Chart::Gtk2::Ex::TreePath::Circular->new_from_string ($str) >> Create and return a new path object positioned at an index given by a string. =item C<< $circpath->next ($model) >> =item C<< $circpath->prev ($model) >> Step C<$circpath> to the next or previous row in the given C<$model>. At the end of the rows C wraps around to the start again, and conversely at the start C wraps around to the end. =item C<< $circpath->row_inserted ($model, $path, $iter) >> =item C<< $circpath->row_deleted ($model, $path) >> =item C<< $circpath->rows_reordered ($model, $path, $iter, $aref) >> Adjust C<$circpath> to maintain it's current position in the presence of the given changes to C<$model>. These functions can be called from the respective model signal, the parameters are the same as to those signals. =back =head1 SEE ALSO L