File Coverage

blib/lib/App/Chart/Gtk2/TickerModel.pm
Criterion Covered Total %
statement 9 11 81.8
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 13 15 86.6


line stmt bran cond sub pod time code
1             # Copyright 2007, 2008, 2009, 2010, 2011, 2017 Kevin Ryde
2              
3             # This file is part of Chart.
4             #
5             # Chart is free software; you can redistribute it and/or modify it under the
6             # terms of the GNU General Public License as published by the Free Software
7             # Foundation; either version 3, or (at your option) any later version.
8             #
9             # Chart is distributed in the hope that it will be useful, but WITHOUT ANY
10             # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11             # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12             # details.
13             #
14             # You should have received a copy of the GNU General Public License along
15             # with Chart. If not, see <http://www.gnu.org/licenses/>.
16              
17              
18             package App::Chart::Gtk2::TickerModel;
19 1     1   395 use 5.010;
  1         3  
20 1     1   4 use strict;
  1         1  
  1         17  
21 1     1   4 use warnings;
  1         2  
  1         24  
22 1     1   139 use Gtk2 1.200; # for working TreeModelFilter modify_func
  0            
  0            
23             use Carp;
24             use Locale::TextDomain ('App-Chart');
25              
26             use Gtk2::Ex::TreeModelFilter::Draggable;
27             use App::Chart;
28              
29              
30             use Glib::Object::Subclass
31             'Gtk2::Ex::TreeModelFilter::Draggable';
32              
33             # uncomment this to run the ### lines
34             # use Smart::Comments;
35              
36             use constant { UP_SPAN => '<span foreground="green">',
37              
38             # a brightish red, for contrast against a black background
39             DOWN_SPAN => '<span foreground="#FF7070">',
40              
41             INPROGRESS_SPAN => '<span foreground="light blue">' };
42              
43             sub new {
44             my ($class, $symlist) = @_;
45              
46             # FIXME: As of Gtk2-Perl 1.201 Gtk2::TreeModelFilter::new() leaks a
47             # reference (its returned object is never destroyed), so go through
48             # Glib::Object::new() instead. Can switch to SUPER::new when ready to
49             # depend on a fixed Gtk2-Perl.
50             #
51             my $self = Glib::Object::new ($class, child_model => $symlist);
52              
53             $self->{'symlist'} = $symlist;
54             $self->set_modify_func ([ 'Glib::String' ], \&_model_filter_func);
55             App::Chart::chart_dirbroadcast()->connect_for_object
56             ('latest-changed', \&_do_latest_changed, $self);
57             return $self;
58             }
59              
60             # 'latest-changed' from DirBroadcast
61             sub _do_latest_changed {
62             my ($self, $changed) = @_;
63             ### Ticker: latest-changed: keys %$changed
64              
65             my $symlist = $self->{'symlist'};
66             $symlist->foreach (sub {
67             my ($self, $path, $iter) = @_;
68             my $symbol = $self->get_value($iter,0);
69             if (exists $changed->{$symbol}) {
70             ### Ticker: changed: $symbol, $path->to_string
71             $self->row_changed ($path, $iter);
72             }
73             return 0; # keep iterating
74             });
75             }
76              
77             sub _model_filter_func {
78             my ($self, $iter, $col) = @_;
79              
80             my $child_model = $self->get_model;
81             my $child_iter = $self->convert_iter_to_child_iter ($iter);
82             my $symbol = $child_model->get_value ($child_iter, 0);
83              
84             require App::Chart::Latest;
85             my $latest = App::Chart::Latest->get ($symbol);
86             return _form ($self, $latest);
87             }
88              
89             # return a pango markup string to display for $latest
90             sub _form {
91             my ($self, $latest) = @_;
92              
93             return ($latest->{__PACKAGE__.'.form'} ||= do {
94             my $symbol = $latest->{'symbol'};
95             my $last = $latest->{'last'}
96             // return $symbol . ' ' . ($latest->{'note'} || __('no data'));
97             my $nf = App::Chart::number_formatter();
98             my $str = $symbol . ' '
99             . $nf->format_number ($last, App::Chart::count_decimals($last), 1);
100              
101             my $change = $latest->{'change'};
102             if ($latest->{'halt'}) { $str .= ' '.__('halt'); }
103             elsif ($latest->{'limit_up'}) { $str .= ' '.__('limit up'); }
104             elsif ($latest->{'limit_down'}) { $str .= ' '.__('limit down'); }
105             elsif (! defined $change) { } # nothing added for undef
106             elsif ($change == 0) { $str .= ' '.__('unch'); }
107             else {
108             $str .= ' ' . ($change > 0 ? '+' : '')
109             . $nf->format_number ($change,App::Chart::count_decimals($change), 1);
110             }
111              
112             my $span;
113             if ($App::Chart::Gtk2::Job::Latest::inprogress{$symbol}) {
114             $span = INPROGRESS_SPAN;
115             } elsif ($latest->{'inprogress'}) {
116             $span = INPROGRESS_SPAN;
117             } elsif (defined $change && $change>0) {
118             $span = UP_SPAN;
119             } elsif (defined $change && $change<0) {
120             $span = DOWN_SPAN;
121             }
122             if ($span) {
123             $str = $span . $str . '</span>';
124             }
125             $str;
126             });
127             }
128              
129             1;
130             __END__
131              
132             =for stopwords symlist ie
133              
134             =head1 NAME
135              
136             App::Chart::Gtk2::TickerModel -- ticker display data model object
137              
138             =for test_synopsis my ($symlist)
139              
140             =head1 SYNOPSIS
141              
142             use App::Chart::Gtk2::TickerModel;
143             my $model = App::Chart::Gtk2::TickerModel->new ($symlist);
144              
145             =head1 OBJECT HIERARCHY
146              
147             C<App::Chart::Gtk2::TickerModel> is a subclass of C<Gtk2::TreeModelFilter>,
148              
149             Glib::Object
150             Gtk2::TreeModelFilter
151             App::Chart::Gtk2::TickerModel
152              
153             =head1 DESCRIPTION
154              
155             A C<App::Chart::Gtk2::TickerModel> object presents the data from a given
156             C<App::Chart::Gtk2::Symlist> in a form suitable for the
157             C<App::Chart::Gtk2::Ticker> widget. This means presenting each symbol as
158             symbol, price, and some Pango spans for up/down colour. Currently this is
159             its sole use.
160              
161             =head1 FUNCTIONS
162              
163             =over 4
164              
165             =item C<< App::Chart::Gtk2::TickerModel->new ($symlist) >>
166              
167             Create and return a C<App::Chart::Gtk2::TickerModel> object presenting the
168             symbols in C<$symlist>.
169              
170             =back
171              
172             =head1 PROPERTIES
173              
174             =over 4
175              
176             =item C<symlist> (C<App::Chart::Gtk2::Symlist> object, read-only)
177              
178             The symlist to track and get data from. The intention is that this is
179             "construct-only", ie. to be set only when first constructing the model. To
180             present a different symlist create a new model.
181              
182             =back
183              
184             =head1 SEE ALSO
185              
186             L<App::Chart::Gtk2::Ticker>
187              
188             =head1 HOME PAGE
189              
190             L<http://user42.tuxfamily.org/chart/index.html>
191              
192             =head1 LICENCE
193              
194             Copyright 2007, 2008, 2009, 2010, 2011, 2017 Kevin Ryde
195              
196             Chart is free software; you can redistribute it and/or modify it under the
197             terms of the GNU General Public License as published by the Free Software
198             Foundation; either version 3, or (at your option) any later version.
199              
200             Chart is distributed in the hope that it will be useful, but WITHOUT ANY
201             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
202             FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
203             details.
204              
205             You should have received a copy of the GNU General Public License along with
206             Chart; see the file F<COPYING>. Failing that, see
207             L<http://www.gnu.org/licenses/>.
208              
209             =cut