Gtk2-Ex-DateSpinner

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

    - in the tests avoid a slew of warnings from Gtk 2.16 when display
      not yet initialized

Version 4,  February 2009
    - avoid some stupid adjustment page size warnings from Gtk 2.14

Version 3,  January 2009
    - fixes for dependencies and some test skips

Version 2,  January 2009
    - new Gtk2::Ex::DateSpinner::CellRenderer with popup datespinner

Version 1,  September 2008
    - the first version

README  view on Meta::CPAN

Gtk2::Ex::DateSpinner is a simple date entry widget using spin buttons
for year, month and day.

    +--------------------------------------+ 
    |  +------+   +----+   +----+          |
    |  | 2008 |^  |  6 |^  | 14 |^   Sat   |
    |  +------+v  +----+v  +----+v         |
    +--------------------------------------+ 

It can be used as an ordinary widget in a dialog or form, and also as
a cell renderer with popup edit in a TreeView or similar.

The prerequisites are Gtk2-Perl, Date::Calc, and my Gtk2-Ex-WidgetBits
and Glib-Ex-ObjectBits.  The DateSpinner home page is

    http://user42.tuxfamily.org/gtk2-ex-datespinner/index.html

devel/entry-completion.pl  view on Meta::CPAN

my $progname = $FindBin::Script;

my $model = Gtk2::ListStore->new ('Glib::String');
$model->insert_with_values (0, 0 => 'food');
$model->insert_with_values (1, 0 => 'foobar');
$model->insert_with_values (2, 0 => 'xyzzy');

my $completion = Gtk2::EntryCompletion->new;
$completion->set_model ($model);
$completion->set_text_column (0);
$completion->set_popup_completion (1);

my $setname = 'Gtk2::Ex::Entry::WithCancel';
$setname =~ tr/:/_/;
$setname .= '_keys';

my $entry = Gtk2::Entry->new;
$entry->set_completion ($completion);

my $toplevel = Gtk2::Window->new('toplevel');
$toplevel->signal_connect (destroy => sub { Gtk2->main_quit; });

devel/entrywithcancel.pl  view on Meta::CPAN

print "$progname: 'F12' keyval=", Gtk2::Gdk->keyval_from_name('F12'), "\n";

my $model = Gtk2::ListStore->new ('Glib::String');
$model->insert_with_values (0, 0 => 'food');
$model->insert_with_values (1, 0 => 'foobar');
$model->insert_with_values (2, 0 => 'xyzzy');

my $completion = Gtk2::EntryCompletion->new;
$completion->set_model ($model);
$completion->set_text_column (0);
$completion->set_popup_completion (1);

my $setname = 'Gtk2::Ex::Entry::WithCancel';
$setname =~ tr/:/_/;
$setname .= '_keys';

if (Gtk2::BindingSet->can('find')) {
  my $bindingset = Gtk2::BindingSet->find ($setname);
  print "$progname: find bindingset '$setname' gives ",($bindingset||'false'),"\n";
}

examples/cellrenderer.pl  view on Meta::CPAN

# a date column in a TreeModel.
#
# As usual the model/view/renderer stuff is diabolically complicated, but
# assuming you've managed to display stuff, the editing is then a matter of
# enabling 'editable' in the renderer and hooking onto its 'edited' signal.
# Writing the new data back to the model, or to disk or wherever, is the
# responsibility of that handler.
#
# The code here is basically the same as you'd do for a plain
# Gtk2::CellRendererText.  But DateSpinner::CellRenderer edits with a
# DateSpinner popup.  The $newstr string passed to the 'edited' signal is
# the new ISO YYYY-MM-DD date.
#
# You can set the 'editable' on the renderer by all the usual model+viewer
# tricks, like getting it from a column or setting it with a data func
# according to the phase of the moon.  That way you can have some cells
# editable and some not.
#
# The text column added here is just for decoration, but you could make it
# editable too.  You can even have multiple renderers in the one column,
# each editable.  The choice between one column with two renderers and two

lib/Gtk2/Ex/DateSpinner/CellRenderer.pm  view on Meta::CPAN

  my $cancelled = $entry->{'editing_cancelled'};
  $self->stop_editing ($cancelled);
  if (! $cancelled) {
    $self->signal_emit ('edited', $self->{'pathstr'}, $entry->get_text);
  }
}

1;
__END__

=for stopwords renderer DateSpinner Gtk2-Ex-DateSpinner YYYY-MM-DD popup decrement Ok Eg Gtk2-Perl Ryde

=head1 NAME

Gtk2::Ex::DateSpinner::CellRenderer -- date cell renderer with DateSpinner for editing

=for test_synopsis my ($treeviewcolumn)

=head1 SYNOPSIS

 use Gtk2::Ex::DateSpinner::CellRenderer;

lib/Gtk2/Ex/DateSpinner/CellRenderer.pm  view on Meta::CPAN


    Gtk2::Object
      Gtk2::CellRenderer
        Gtk2::CellRendererText
          Gtk2::Ex::DateSpinner::CellRenderer

=head1 DESCRIPTION

C<DateSpinner::CellRenderer> displays an ISO format YYYY-MM-DD date as a
text field.  Editing the field presents both a C<Gtk2::Entry> widget and a
popup C<Gtk2::Ex::DateSpinner>.

    +------------+
    | 2008-06-14 |
    +------------+
    +-----------------------------------------------------+
    | +------+   +----+   +----+         +----+ +------+  |
    | | 2008 |^  |  6 |^  | 14 |^  Sat   | Ok | |Cancel|  |
    | +------+v  +----+v  +----+v        +----+ +------+  |
    +-----------------------------------------------------+

The popup allows mouse clicks or arrow keys to increment or decrement the
date components.  This is good if you often just want to bump a date up or
down.  And when you're displaying YYYY-MM-DD it makes sense to present it
like that for editing.  Of course there's a huge range of other ways you
could display or edit a date.

See F<examples/cellrenderer.pl> for a complete program with a C<TreeView>
and a C<DateSpinner::CellRenderer>.

=head2 Details

lib/Gtk2/Ex/DateSpinner/CellRenderer.pm  view on Meta::CPAN

Create and return a new DateSpinner::CellRenderer object.  Optional key/value
pairs set initial properties as per C<< Glib::Object->new >>.  Eg.

    my $renderer = Gtk2::Ex::DateSpinner::CellRenderer->new
                     (editable => 1);

=back

=head1 OTHER NOTES

C<DateSpinner::CellRenderer> creates new a new entry widget and a new popup
window for each edit and both are destroyed on accept or cancel.  This is
the same as the base C<CellRendererText> does.  It's a little wasteful, but
is normally fast enough for casual editing and it might save some memory in
between.

The code for the popup is in the C<Gtk2::Ex::DateSpinner::PopupForEntry>
component.  It's not loaded until the first edit and is only meant for
internal use as yet.

=head1 SEE ALSO

L<Gtk2::Ex::DateSpinner>, L<Gtk2::CellRendererText>

Gtk2-Perl F<examples/cellrenderer_date.pl> does a similar display/edit
popping up a C<Gtk2::Calendar>.  See
L<Gtk2::Ex::Datasheet::DBI|Gtk2::Ex::Datasheet::DBI> for a version of it in

lib/Gtk2/Ex/DateSpinner/PopupForEntry.pm  view on Meta::CPAN

use Gtk2;
use List::Util qw(min max);

our $VERSION = 10;

use Glib::Object::Subclass
  'Gtk2::Window',
  properties => [ Glib::ParamSpec->object
                  ('entry',
                   'Entry widget',
                   'The Gtk2::Entry widget to read/write with the popup.',
                   'Gtk2::Widget',
                   Glib::G_PARAM_READWRITE()),
                ];

sub INIT_INSTANCE {
  my ($self) = @_;

  $self->set_decorated (0);
  $self->set_flags('can-focus');

lib/Gtk2/Ex/DateSpinner/PopupForEntry.pm  view on Meta::CPAN

  if ($self->{'change_in_progress'}) { return; }
  my $entry = $self->{'entry'} || return;

  local $self->{'change_in_progress'} = 1;
  $entry->set_text ($datespinner->get_value);
}

sub _do_entry_editing_done {
  my ($entry, $ref_weak_self) = @_;
  my $self = $$ref_weak_self || return;
  ### PopupForEntry: _do_entry_editing_done(), hide popup ...
  $self->hide;
}

# 'activate' on the spin buttons
# 'clicked' on the 'gtk-ok' button
#
sub _do_activate {
  my ($widget) = @_;
  ### PopupForEntry _do_activate() ...
  my $self = $widget->get_toplevel;

lib/Gtk2/Ex/DateSpinner/PopupForEntry.pm  view on Meta::CPAN


  $self->hide;
  my $entry = $self->{'entry'} || return;  # maybe already gone
  $entry->{'editing_cancelled'} = 1;
  $entry->editing_done;
  $entry->remove_widget;
}

# 'size-allocate' on the entry widget
#
# Finding the right time to position the popup is a bit painful.
# GtkTreeView and GtkIconView add the editable to themselves and map it with
# default height 1, then focus to it, then size_allocate it up to the cell
# size.  So to position underneath it we only know the right height after
# that size-allocate.  Positioning earlier at the map or the focus state
# ends up with an unattractive visible move of the popup window downwards.
#
# FIXME: Depending on the sequence of actions in TreeView is a bit nasty,
# maybe it'd at least be worth a recheck of the position on getting to
# Glib::Idle after a start_editing.
#
sub _do_position {
  my ($entry) = @_;
  my $ref_weak_self = $_[-1];
  my $self = $$ref_weak_self || return;

lib/Gtk2/Ex/DateSpinner/PopupForEntry.pm  view on Meta::CPAN

    # below is past bottom of screen, try above
    $win_y = $y - $req->height;
    if ($win_y < 0) {
      # above is past top of screen, clamp to top
      $win_y = 0;
    }
  }

  # 'gravity' (GdkGravity) doesn't really help to position above a selected
  # position for a one-off move, it only works if set and left.  Could be ok
  # since this popup is supposed to be private, but a bit easier to stay
  # default north-west for now.
  #
  $toplevel->move ($win_x, $win_y);
}

1;
__END__

=for stopwords popup DateSpinner Gtk2-Ex-DateSpinner Ok PopupForEntry Ryde

=head1 NAME

Gtk2::Ex::DateSpinner::PopupForEntry -- popup DateSpinner for a Gtk2::Entry

=head1 SYNOPSIS

 use Gtk2::Ex::DateSpinner::PopupForEntry;
 my $entry = Gtk2::Ex::DateSpinner::PopupForEntry->new;

=head1 WIDGET HIERARCHY

C<Gtk2::Ex::DateSpinner::PopupForEntry> is a subclass of C<Gtk2::Window>.

    Gtk2::Widget
      Gtk2::Container
        Gtk2::Bin
          Gtk2::Window
            Gtk2::Ex::DateSpinner::PopupForEntry

=head1 DESCRIPTION

B<Caution: This is internals of C<Gtk2::Ex::DateSpinner::CellRenderer>.  The
idea of a popup under an edited cell might be split out under a new name at
some time, or even the idea of a DateSpinner popup standing alone.>

C<DateSpinner::PopupForEntry> holds a C<Gtk2::Ex::DateSpinner> and Ok and
Cancel buttons.  It positions itself under a given C<Gtk2::Entry> (or
subclass of C<Gtk2::Entry>) and communicates its value back and forward with
that Entry for dual editing.  Only a weak reference is held on the Entry and
when the entry is destroyed the PopupForEntry is closed and destroyed too.

=head1 PROPERTIES

=over 4



( run in 1.272 second using v1.01-cache-2.11-cpan-364913b4093 )