line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyright 2006, 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
|
|
|
|
|
|
|
package App::Chart::Gtk2::Ticker; |
18
|
2
|
|
|
2
|
|
885
|
use 5.008; |
|
2
|
|
|
|
|
7
|
|
19
|
2
|
|
|
2
|
|
9
|
use strict; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
33
|
|
20
|
2
|
|
|
2
|
|
8
|
use warnings; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
50
|
|
21
|
2
|
|
|
2
|
|
8
|
use Carp; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
130
|
|
22
|
2
|
|
|
2
|
|
292
|
use Gtk2 1.200; # for working TreeModelFilter modify_func |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use Gtk2::Ex::TickerView; |
24
|
|
|
|
|
|
|
use List::Util qw(min max); |
25
|
|
|
|
|
|
|
use Locale::TextDomain 'App-Chart'; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
use App::Chart::Glib::Ex::MoreUtils; |
28
|
|
|
|
|
|
|
use Glib::Ex::SignalIds; |
29
|
|
|
|
|
|
|
use Gtk2::Ex::Units; |
30
|
|
|
|
|
|
|
use App::Chart; |
31
|
|
|
|
|
|
|
use App::Chart::Gtk2::GUI; |
32
|
|
|
|
|
|
|
use App::Chart::Gtk2::Symlist; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# uncomment this to run the ### lines |
35
|
|
|
|
|
|
|
#use Smart::Comments; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
BEGIN { |
38
|
|
|
|
|
|
|
Glib::Type->register_enum ('App::Chart::Gtk2::Ticker::menu_position', |
39
|
|
|
|
|
|
|
'centre' => 0, |
40
|
|
|
|
|
|
|
'pointer' => 1); |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
use Glib::Object::Subclass |
43
|
|
|
|
|
|
|
'Gtk2::Ex::TickerView', |
44
|
|
|
|
|
|
|
signals => { button_press_event => \&_do_button_press_event, |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
menu_created => { param_types => ['Gtk2::Menu'], |
47
|
|
|
|
|
|
|
return_type => undef, |
48
|
|
|
|
|
|
|
}, |
49
|
|
|
|
|
|
|
menu_popup => { param_types => ['Glib::Int', |
50
|
|
|
|
|
|
|
'App::Chart::Gtk2::Ticker::menu_position'], |
51
|
|
|
|
|
|
|
return_type => undef, |
52
|
|
|
|
|
|
|
class_closure => \&_do_menu_popup_action, |
53
|
|
|
|
|
|
|
flags => [ 'run-last', 'action' ], |
54
|
|
|
|
|
|
|
}, |
55
|
|
|
|
|
|
|
}, |
56
|
|
|
|
|
|
|
properties => [Glib::ParamSpec->object |
57
|
|
|
|
|
|
|
('symlist', |
58
|
|
|
|
|
|
|
'symlist', |
59
|
|
|
|
|
|
|
'App::Chart::Gtk2::Symlist object for the symbols to display.', |
60
|
|
|
|
|
|
|
# App::Chart::Gtk2::Symlist::Join is a ListModelConcat not |
61
|
|
|
|
|
|
|
# a Symlist subclass, allow that by just Glib::Object here |
62
|
|
|
|
|
|
|
'Glib::Object', |
63
|
|
|
|
|
|
|
Glib::G_PARAM_READWRITE), |
64
|
|
|
|
|
|
|
]; |
65
|
|
|
|
|
|
|
App::Chart::Gtk2::GUI::chart_style_class (__PACKAGE__); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# priority level "gtk" treating this as widget level default, for overriding |
68
|
|
|
|
|
|
|
# by application or user RC |
69
|
|
|
|
|
|
|
Gtk2::Rc->parse_string (<<'HERE'); |
70
|
|
|
|
|
|
|
binding "App__Chart__Gtk2__Ticker_keys" { |
71
|
|
|
|
|
|
|
bind "F10" { "menu_popup" (0, centre) } |
72
|
|
|
|
|
|
|
bind "Pointer_Button3" { "menu_popup" (3, pointer) } |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
class "App__Chart__Gtk2__Ticker" binding:gtk "App__Chart__Gtk2__Ticker_keys" |
75
|
|
|
|
|
|
|
HERE |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub INIT_INSTANCE { |
78
|
|
|
|
|
|
|
my ($self) = @_; |
79
|
|
|
|
|
|
|
$self->add_events (['button-press-mask', 'key-press-mask']); |
80
|
|
|
|
|
|
|
$self->set (fixed_height_mode => 1); |
81
|
|
|
|
|
|
|
$self->set_flags ('can-focus'); |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
my $renderer = Gtk2::CellRendererText->new; |
84
|
|
|
|
|
|
|
$renderer->set (xpad => Gtk2::Ex::Units::em($self)); |
85
|
|
|
|
|
|
|
$self->pack_start ($renderer, 0); |
86
|
|
|
|
|
|
|
$self->set_attributes ($renderer, markup => 0); |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# default Favourites symlist, unless it's empty and All is not in which |
89
|
|
|
|
|
|
|
# case use All |
90
|
|
|
|
|
|
|
require App::Chart::Gtk2::Symlist::Favourites; |
91
|
|
|
|
|
|
|
my $symlist = App::Chart::Gtk2::Symlist::Favourites->instance; |
92
|
|
|
|
|
|
|
if ($symlist->is_empty) { |
93
|
|
|
|
|
|
|
require App::Chart::Gtk2::Symlist::All; |
94
|
|
|
|
|
|
|
my $all = App::Chart::Gtk2::Symlist::All->instance; |
95
|
|
|
|
|
|
|
if (! $all->is_empty) { |
96
|
|
|
|
|
|
|
$symlist = $all; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
$self->set (symlist => $symlist); |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub FINALIZE_INSTANCE { |
103
|
|
|
|
|
|
|
my ($self) = @_; |
104
|
|
|
|
|
|
|
# Gtk2::Menu doesn't go away just by weakening if currently popped-up |
105
|
|
|
|
|
|
|
# (because it's then a toplevel presumably); doing ->popdown() works, but |
106
|
|
|
|
|
|
|
# ->destroy() seems the best idea |
107
|
|
|
|
|
|
|
if (my $menu = $self->{'menu'}) { |
108
|
|
|
|
|
|
|
$menu->destroy; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub SET_PROPERTY { |
113
|
|
|
|
|
|
|
my ($self, $pspec, $newval) = @_; |
114
|
|
|
|
|
|
|
my $pname = $pspec->get_name; |
115
|
|
|
|
|
|
|
my $oldval = $self->{$pname}; |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
if ($pname eq 'symlist' && ($newval||0) != ($oldval||0)) { |
118
|
|
|
|
|
|
|
### Ticker: "$self changed symlist" |
119
|
|
|
|
|
|
|
my $symlist = $newval; |
120
|
|
|
|
|
|
|
if (defined $symlist && ! $symlist->isa('App::Chart::Gtk2::Symlist')) { |
121
|
|
|
|
|
|
|
croak "App::Chart::Gtk2::Ticker.symlist must be an App::Chart::Gtk2::Symlist"; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
$self->{$pname} = $newval; # per default GET_PROPERTY |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
require App::Chart::Gtk2::TickerModel; |
126
|
|
|
|
|
|
|
my $model = $self->{'symlist_model'} |
127
|
|
|
|
|
|
|
= $symlist && App::Chart::Gtk2::TickerModel->new ($symlist); |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
my $ref_weak_self = App::Chart::Glib::Ex::MoreUtils::ref_weak ($self); |
130
|
|
|
|
|
|
|
$self->{'symlist_model_ids'} = $model && do { |
131
|
|
|
|
|
|
|
Glib::Ex::SignalIds->new |
132
|
|
|
|
|
|
|
($model, |
133
|
|
|
|
|
|
|
$model->signal_connect (row_deleted => \&_do_row_deleted, |
134
|
|
|
|
|
|
|
$ref_weak_self), |
135
|
|
|
|
|
|
|
$model->signal_connect (row_inserted => \&_do_row_inserted, |
136
|
|
|
|
|
|
|
$ref_weak_self)) |
137
|
|
|
|
|
|
|
}; |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
$self->set (model => $model); |
140
|
|
|
|
|
|
|
$self->{'showing_empty'} = 0; |
141
|
|
|
|
|
|
|
_check_empty ($self); |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
} else { |
144
|
|
|
|
|
|
|
$self->{$pname} = $newval; # per default GET_PROPERTY |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# 'button-press-event' class closure |
149
|
|
|
|
|
|
|
sub _do_button_press_event { |
150
|
|
|
|
|
|
|
my ($self, $event) = @_; |
151
|
|
|
|
|
|
|
require App::Chart::Gtk2::Ex::BindingBits; |
152
|
|
|
|
|
|
|
App::Chart::Gtk2::Ex::BindingBits::activate_button_event |
153
|
|
|
|
|
|
|
('App__Chart__Gtk2__Ticker_keys', $event, $self); |
154
|
|
|
|
|
|
|
return shift->signal_chain_from_overridden(@_); |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# 'menu-popup' action signal class closure |
158
|
|
|
|
|
|
|
sub _do_menu_popup_action { |
159
|
|
|
|
|
|
|
my ($self, $button, $where) = @_; |
160
|
|
|
|
|
|
|
### Ticker: "menu-popup action $button $where" |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
my $position_func; # undef for mouse position if $where empty or undef |
163
|
|
|
|
|
|
|
if ($where && $where ne 'pointer') { |
164
|
|
|
|
|
|
|
$position_func = $self->can("menu_position_func_$where"); |
165
|
|
|
|
|
|
|
unless ($position_func) { |
166
|
|
|
|
|
|
|
Glib->warning (undef, warn "Ticker: unrecognised menu position '$where', default to mouse pointer"); |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
my $symbol; |
170
|
|
|
|
|
|
|
if (! $where || $where eq 'pointer') { |
171
|
|
|
|
|
|
|
my $event = Gtk2->get_current_event; |
172
|
|
|
|
|
|
|
require Gtk2::Ex::WidgetBits; |
173
|
|
|
|
|
|
|
if (my ($x,$y) = Gtk2::Ex::WidgetBits::xy_root_to_widget ($self, |
174
|
|
|
|
|
|
|
$event->x_root, |
175
|
|
|
|
|
|
|
$event->y_root)) { |
176
|
|
|
|
|
|
|
if (my $path = $self->get_path_at_pos ($x, $y)) { |
177
|
|
|
|
|
|
|
if (my $model = $self->get('symlist')) { |
178
|
|
|
|
|
|
|
if (my $iter = $model->get_iter ($path)) { |
179
|
|
|
|
|
|
|
$symbol = $model->get($iter, $model->COL_SYMBOL); |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
my $menu = $self->menu; |
186
|
|
|
|
|
|
|
$menu->set_screen ($self->get_screen); |
187
|
|
|
|
|
|
|
$menu->set (symbol => $symbol); |
188
|
|
|
|
|
|
|
$menu->popup (undef, # parent menushell |
189
|
|
|
|
|
|
|
undef, # parent menuitem |
190
|
|
|
|
|
|
|
$position_func, |
191
|
|
|
|
|
|
|
App::Chart::Glib::Ex::MoreUtils::ref_weak($self), # position func data |
192
|
|
|
|
|
|
|
$button, |
193
|
|
|
|
|
|
|
Gtk2->get_current_event_time); |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
# 'row-deleted' signal on symlist model |
197
|
|
|
|
|
|
|
sub _do_row_deleted { |
198
|
|
|
|
|
|
|
my ($model, $path, $ref_weak_self) = @_; |
199
|
|
|
|
|
|
|
my $self = $$ref_weak_self || return; |
200
|
|
|
|
|
|
|
_check_empty ($self); |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
# 'row-inserted' signal on symlist model |
203
|
|
|
|
|
|
|
sub _do_row_inserted { |
204
|
|
|
|
|
|
|
my ($model, $path, $iter, $ref_weak_self) = @_; |
205
|
|
|
|
|
|
|
my $self = $$ref_weak_self || return; |
206
|
|
|
|
|
|
|
_check_empty ($self); |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
sub _check_empty { |
209
|
|
|
|
|
|
|
my ($self) = @_; |
210
|
|
|
|
|
|
|
my $symlist = $self->{'symlist'}; |
211
|
|
|
|
|
|
|
my $empty = !$symlist || $symlist->is_empty; |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
if ($empty && ! $self->{'showing_empty'}) { |
214
|
|
|
|
|
|
|
# become empty |
215
|
|
|
|
|
|
|
my $empty_model = ($self->{'empty_model'} ||= do { |
216
|
|
|
|
|
|
|
my $liststore = Gtk2::ListStore->new ('Glib::String'); |
217
|
|
|
|
|
|
|
$liststore->append; |
218
|
|
|
|
|
|
|
$liststore; |
219
|
|
|
|
|
|
|
}); |
220
|
|
|
|
|
|
|
my $message = $symlist |
221
|
|
|
|
|
|
|
? __x('{symlistname} list is empty ... ', |
222
|
|
|
|
|
|
|
symlistname => $symlist->name) |
223
|
|
|
|
|
|
|
: __('No symlist ... '); |
224
|
|
|
|
|
|
|
$empty_model->set_value ($empty_model->get_iter_first, |
225
|
|
|
|
|
|
|
0 => $message); |
226
|
|
|
|
|
|
|
$self->set (model => $empty_model); |
227
|
|
|
|
|
|
|
$self->{'showing_empty'} = 1; |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
} elsif ($self->{'showing_empty'} && ! $empty) { |
230
|
|
|
|
|
|
|
$self->set (model => $self->{'symlist_model'}); |
231
|
|
|
|
|
|
|
$self->{'showing_empty'} = 0; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
# create and return Gtk2::Menu widget |
236
|
|
|
|
|
|
|
sub menu { |
237
|
|
|
|
|
|
|
my ($self) = @_; |
238
|
|
|
|
|
|
|
return ($self->{'menu'} ||= do { |
239
|
|
|
|
|
|
|
### Ticker menu doesn't exist, creating |
240
|
|
|
|
|
|
|
require App::Chart::Gtk2::TickerMenu; |
241
|
|
|
|
|
|
|
my $menu = App::Chart::Gtk2::TickerMenu->new (ticker => $self); |
242
|
|
|
|
|
|
|
$self->signal_emit ('menu-created', $menu); |
243
|
|
|
|
|
|
|
$menu; |
244
|
|
|
|
|
|
|
}); |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
# and also 'activate' signal on Help menu item |
248
|
|
|
|
|
|
|
sub help { |
249
|
|
|
|
|
|
|
require App::Chart::Manual; |
250
|
|
|
|
|
|
|
App::Chart::Manual->open(__p('manual-node','Ticker')); |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
254
|
|
|
|
|
|
|
# position funcs |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
sub menu_position_func_centre { |
257
|
|
|
|
|
|
|
require Gtk2::Ex::MenuBits; |
258
|
|
|
|
|
|
|
goto &Gtk2::Ex::MenuBits::position_widget_topcentre; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
1; |
263
|
|
|
|
|
|
|
__END__ |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=for stopwords symlist submenu Symlist boolean ie |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
=head1 NAME |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
App::Chart::Gtk2::Ticker -- stock ticker widget |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
=head1 SYNOPSIS |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
use App::Chart::Gtk2::Ticker; |
274
|
|
|
|
|
|
|
my $ticker = App::Chart::Gtk2::Ticker->new; |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
my $symlist = App::Chart::Gtk2::Symlist::All->instance; |
277
|
|
|
|
|
|
|
$ticker->set (symlist => $symlist); |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=head1 WIDGET HIERARCHY |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
C<App::Chart::Gtk2::Ticker> is a subclass of C<Gtk2::Ex::TickerView>, |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
Gtk2::Widget |
284
|
|
|
|
|
|
|
... |
285
|
|
|
|
|
|
|
Gtk2::Ex::TickerView |
286
|
|
|
|
|
|
|
App::Chart::Gtk2::Ticker |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=head1 DESCRIPTION |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
A C<App::Chart::Gtk2::Ticker> widget showing stock quotes scrolling across the |
291
|
|
|
|
|
|
|
window for a given symlist (L<App::Chart::Gtk2::Symlist>) |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head1 FUNCTIONS |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=over 4 |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=item C<< App::Chart::Gtk2::Ticker->new (key => value, ...) >> |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
Create and return a C<App::Chart::Gtk2::Ticker> widget. Optional key/value |
300
|
|
|
|
|
|
|
pairs can be given to set initial properties as per |
301
|
|
|
|
|
|
|
C<< Glib::Object->new >>. |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=item C<< $ticker->menu() >> |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
Return the C<Gtk2::Menu> which is popped up by mouse button 3 in the ticker. |
306
|
|
|
|
|
|
|
An application can add items to this, such as "Hide" or "Quit", or perhaps a |
307
|
|
|
|
|
|
|
submenu to change what's displayed. |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
=item C<< $ticker->refresh() >> |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
Download fresh prices for the symbols displayed. This is the "Refresh" item |
312
|
|
|
|
|
|
|
in the button-3 menu. |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=item C<< $ticker->help() >> |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
Open the Chart manual at the section on the ticker. This is the "Help" item |
317
|
|
|
|
|
|
|
in the button-3 menu. |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=back |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
=head1 PROPERTIES |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=over 4 |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=item symlist (C<App::Chart::Gtk2::Symlist>, default favourites or all) |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
A Symlist object which is the stock symbols to display. |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=back |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head1 SEE ALSO |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
L<App::Chart::Gtk2::TickerMain>, |
334
|
|
|
|
|
|
|
L<App::Chart::Gtk2::Symlist>, |
335
|
|
|
|
|
|
|
C<Gtk2::Ex::TickerView> |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=head1 HOME PAGE |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
L<http://user42.tuxfamily.org/chart/index.html> |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=head1 LICENCE |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2017 Kevin Ryde |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
Chart is free software; you can redistribute it and/or modify it under the |
346
|
|
|
|
|
|
|
terms of the GNU General Public License as published by the Free Software |
347
|
|
|
|
|
|
|
Foundation; either version 3, or (at your option) any later version. |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
Chart is distributed in the hope that it will be useful, but WITHOUT ANY |
350
|
|
|
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
351
|
|
|
|
|
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
352
|
|
|
|
|
|
|
details. |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with |
355
|
|
|
|
|
|
|
Chart; see the file F<COPYING>. Failing that, see |
356
|
|
|
|
|
|
|
L<http://www.gnu.org/licenses/>. |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
=cut |