File Coverage

lib/Gtk2/Ex/MindMapView/Content/EllipsisText.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package Gtk2::Ex::MindMapView::Content::EllipsisText;
2              
3             our $VERSION = '0.000001';
4              
5 9     9   47 use warnings;
  9         16  
  9         1634  
6 9     9   54 use strict;
  9         25  
  9         431  
7 9     9   56 use Carp;
  9         33  
  9         847  
8              
9 9     9   50 use constant MAX_WIDTH=>300; # pixels.
  9         19  
  9         967  
10 9     9   60 use constant MAX_HEIGHT=>300; # pixels.
  9         29  
  9         448  
11              
12 9     9   98 use List::Util;
  9         25  
  9         588  
13              
14 9     9   6802 use Gnome2::Canvas;
  0            
  0            
15              
16             use Gtk2::Ex::MindMapView::ArgUtils;
17             use Gtk2::Ex::MindMapView::Content;
18              
19             use base 'Gtk2::Ex::MindMapView::Content';
20              
21             sub new
22             {
23             my $class = shift(@_);
24              
25             my $self = $class->SUPER::new(@_);
26              
27             my %attributes = @_;
28              
29             # args_valid(\%attributes, qw(group x y width height text text_color_gdk font_desc));
30              
31             args_required(\%attributes, qw(group text));
32              
33             my $canvas = $self->{group}->canvas();
34              
35             arg_default($self, "font_desc", Gtk2::Pango::FontDescription->from_string('Ariel Normal 10'));
36              
37             arg_default($self, "text_color_gdk", Gtk2::Gdk::Color->parse('black'));
38              
39             $self->{image} = $self->content_get_image();
40              
41             # Normally the text is made to fit the space determined by the
42             # width and height properties. On instantiation, the initial size
43             # of the text is determined by the text itself and the MAX_WIDTH.
44              
45             $self->{min_height} = $self->{image}->get('text-height');
46              
47             $self->{height} = $self->{image}->get('text-height');
48              
49             $self->{width} = $self->{image}->get('text-width');
50              
51             if ($self->{width} > MAX_WIDTH)
52             {
53             $self->{width} = MAX_WIDTH;
54              
55             _layout_text($self);
56             }
57              
58             $self->{image}->set(clip=>1);
59              
60             $self->{image}->set(clip_height=>$self->{height});
61              
62             $self->{image}->set(clip_width=>$self->{width});
63              
64             # print "EllipsisText, new, height: $self->{height} width: $self->{width}\n";
65              
66             return $self;
67             }
68              
69              
70             # my $image = $content->content_get_image();
71              
72             sub content_get_image
73             {
74             my $self = shift(@_);
75            
76             my $image = Gnome2::Canvas::Item->new($self->{group}, 'Gnome2::Canvas::Text',
77             text=>$self->{text},
78             font_desc=>$self->{font_desc},
79             fill_color_gdk=>$self->{text_color_gdk}
80             );
81             return $image;
82             }
83              
84              
85             # $self->content_set_x($value);
86              
87             sub content_set_x
88             {
89             my ($self, $value) = @_;
90              
91             $self->{image}->set(x=>$value);
92             }
93              
94              
95             # $self->content_set_y($value);
96              
97             sub content_set_y
98             {
99             my ($self, $value) = @_;
100              
101             $self->{image}->set(y=>$value);
102             }
103              
104              
105             # $self->content_set_width($value);
106              
107             sub content_set_width
108             {
109             my ($self, $value) = @_;
110              
111             $self->{image}->set('clip-width'=>$value);
112              
113             _layout_text($self);
114             }
115              
116              
117             # $self->content_set_height($value);
118              
119             sub content_set_height
120             {
121             my ($self, $value) = @_;
122              
123             $self->{image}->set('clip-height'=>$value);
124            
125             _layout_text($self);
126             }
127              
128              
129             # $self->content_set_param($param_name, $value);
130              
131             sub content_set_param
132             {
133             my ($self, $param_name, $value) = @_;
134              
135             $self->{image}->set($param_name=>$value);
136             }
137              
138              
139             # $content->set(x=>0, y=>10, width=>20, height=>30);
140              
141             sub set
142             {
143             my $self = shift(@_);
144              
145             my %attributes = @_;
146              
147             foreach my $param_name (keys %attributes)
148             {
149             my $value = $attributes{$param_name};
150              
151             if ($param_name eq 'text_color_gdk')
152             {
153             $self->{text_color_gdk} = $value;
154              
155             $self->{image}->set('fill-color-gdk'=>$value);
156              
157             next;
158             }
159              
160             if ($param_name eq 'text')
161             {
162             $self->{text} = $value;
163              
164             _layout_text($self);
165              
166             next;
167             }
168              
169             $self->SUPER::set($param_name=>$value);
170             }
171             }
172              
173              
174             # _layout_text: Layout the text to fit into the area defined by the
175             # width and height properties. Append an ellipsis if the text won't
176             # fit in the area. This is done because Gnome2::Canvas::Text does not
177             # have the hooks we need to get at it's internal layout.
178              
179             sub _layout_text
180             {
181             my $self = shift(@_);
182              
183             my $text = $self->{text};
184              
185             my $height = $self->{height};
186              
187             my $width = $self->{width};
188              
189             $self->{image}->set(text=>$text);
190              
191             my $line_height = $self->{image}->get('text-height');
192              
193             my @words = split " ", $text;
194              
195             my $rows = List::Util::max(1, int($height / $line_height));
196              
197             my @display_lines = ();
198              
199             # print "EllipsisText, line_height: $line_height height: $height width: $width rows: $rows words: @words\n";
200              
201             for my $i (1..$rows)
202             {
203             my $line = "";
204              
205             my $word = shift(@words);
206              
207             last if (!defined $word);
208              
209             my $line_candidate = $word;
210              
211             $self->{image}->set(text=>$line_candidate);
212              
213             while ($self->{image}->get('text-width') <= $width)
214             {
215             $line = $line_candidate;
216              
217             $word = shift(@words);
218              
219             last if (!defined $word);
220              
221             $line_candidate = "$line_candidate $word";
222              
223             $self->{image}->set(text=>$line_candidate);
224             }
225              
226             if ($line eq "") # Couldn't fit a word on the line.
227             {
228             push @display_lines, $line_candidate;
229             }
230             else
231             {
232             unshift @words, $word if (defined $word);
233              
234             push @display_lines, $line;
235             }
236             }
237              
238             if ((scalar @words) > 0) # Couldn't fit entire text.
239             {
240             my $last_line = pop(@display_lines);
241              
242             if (!defined $last_line)
243             {
244             push @display_lines, " ...";
245             }
246             else
247             {
248             $self->{image}->set(text=>"$last_line ...");
249              
250             while ($self->{image}->get('text-width') > $width)
251             {
252             my @words = split " ", $last_line;
253              
254             pop @words;
255              
256             last if ((scalar @words) == 0);
257              
258             $last_line = join " ", @words;
259              
260             $self->{image}->set(text=>"$last_line ...");
261             }
262              
263             push @display_lines, "$last_line ...";
264             }
265             }
266              
267             $self->{image}->set(text=>(join "\n", @display_lines));
268             }
269              
270              
271              
272             1; # Magic true value required at end of module
273             __END__