File Coverage

blib/lib/Gtk2/Ex/EntryBits.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             # Copyright 2007, 2008, 2009, 2010, 2011, 2012 Kevin Ryde
2              
3             # This file is part of Gtk2-Ex-WidgetBits.
4             #
5             # Gtk2-Ex-WidgetBits is free software; you can redistribute it and/or
6             # modify it under the terms of the GNU General Public License as published
7             # by the Free Software Foundation; either version 3, or (at your option) any
8             # later version.
9             #
10             # Gtk2-Ex-WidgetBits is distributed in the hope that it will be useful,
11             # but WITHOUT ANY WARRANTY; without even the implied warranty of
12             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13             # Public License for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with Gtk2-Ex-WidgetBits. If not, see .
17              
18             package Gtk2::Ex::EntryBits;
19 1     1   815 use 5.008;
  1         4  
  1         38  
20 1     1   6 use strict;
  1         2  
  1         33  
21 1     1   5 use warnings;
  1         2  
  1         43  
22 1     1   5 use List::Util 'max';
  1         4  
  1         116  
23 1     1   616 use Gtk2;
  0            
  0            
24              
25             use Exporter;
26             our @ISA = ('Exporter');
27             our @EXPORT_OK = qw(select_region_noclip
28             x_to_text_index
29             scroll_number_handler);
30              
31             our $VERSION = 48;
32              
33             sub select_region_noclip {
34             my ($entry, $start, $end) = @_;
35              
36             # Gtk2::Entry::select_region won't error out, but a subclassed method
37             # might, or $entry might not be a Gtk2::Entry at all, so guard the temp
38             # change to the realized() flag
39             #
40             require Scope::Guard;
41             my $save = $entry->realized;
42             my $guard = Scope::Guard->new (sub { $entry->realized($save) });
43              
44             $entry->realized (0);
45             $entry->select_region ($start, $end);
46             }
47              
48             sub x_to_text_index {
49             my ($entry, $x) = @_;
50             my $layout = $entry->get_layout;
51             my $layout_line = $layout->get_line(0) || return undef;
52              
53             my ($x_offset, $y_offset) = $entry->get_layout_offsets;
54             $x -= $x_offset;
55             ### $x_offset
56              
57             require Gtk2::Pango;
58             my ($inside, $index, $trailing)
59             = $layout_line->x_to_index($x * Gtk2::Pango::PANGO_SCALE()
60             + int(Gtk2::Pango::PANGO_SCALE()/2));
61             ### $inside
62             ### $index
63             ### $trailing
64              
65             # $trailing is set when in the second half of a char (is that right?).
66             # Don't want to apply it unless past the end of the string, so not $inside.
67             if (! $inside) {
68             $index += $trailing;
69             }
70             return $entry->layout_index_to_text_index($index);
71             }
72              
73             my %direction_to_offset = (up => 1,
74             down => -1);
75             sub scroll_number_handler {
76             my ($entry, $event) = @_;
77             ### EntryBits scroll_number() ...
78              
79             if (my $num_increment = $direction_to_offset{$event->direction}) {
80             if ($event->state & 'control-mask') {
81             $num_increment *= 10;
82             }
83             if (defined (my $pos = x_to_text_index($entry,$event->x))) {
84             my $text = $entry->get_text;
85             my $text_at = substr($text,$pos);
86             if ($text_at =~ /^(\d+)/) {
87             my $num_len = length($1);
88             my $text_before = substr($text,0,$pos);
89             $text_before =~ /(\d*)$/;
90             $pos -= length($1);
91             $num_len += length($1);
92              
93             my $old_len = length($text);
94             my $num = substr($text, $pos, $num_len);
95             $text = substr($text, 0, $pos)
96             . max(0, $num+$num_increment)
97             . substr($text, $pos+$num_len);
98              
99             my $cursor_position = $entry->get_position;
100             $entry->set_text ($text);
101             $entry->set_position ($cursor_position
102             + length($text)-$old_len);
103              
104             $entry->activate;
105             return 1; # Gtk2::EVENT_STOP
106             }
107             }
108             }
109             return 0; # Gtk2::EVENT_PROPAGATE
110             }
111              
112             1;
113             __END__