App-Chart
view release on metacpan or search on metacpan
lib/App/Chart/Gtk2/Main.pm view on Meta::CPAN
},
},
{ name => 'Centre',
label => __('_Centre'),
accelerator => __p('Main-accelerator-key','<Ctrl>C'),
callback => sub { my ($action, $self) = @_;
$self->{'view'}->centre; }
},
{ name => 'ZoomInX',
label => __('Zoom Wider'),
accelerator => __p('Main-accelerator-key','W'),
callback => sub { my ($action, $self) = @_;
$self->{'view'}->zoom (1.5, 1) }
},
{ name => 'ZoomOutX',
label => __('Zoom Narrower'),
accelerator => __p('Main-accelerator-key','<Shift>W'),
callback => sub { my ($action, $self) = @_;
$self->{'view'}->zoom (0.75, 1) }
},
{ name => 'ZoomInY',
stock_id => 'gtk-zoom-in',
accelerator => __p('Main-accelerator-key','Z'),
callback => sub { my ($action, $self) = @_;
$self->{'view'}->zoom (1, 1.5) }
},
{ name => 'ZoomOutY',
stock_id => 'gtk-zoom-out',
accelerator => __p('Main-accelerator-key','<Shift>Z'),
callback => sub { my ($action, $self) = @_;
$self->{'view'}->zoom (1, 1/1.5) }
},
{ name => 'Redraw',
label => __('_Redraw'),
accelerator => __p('Main-accelerator-key','<Ctrl>L'),
tooltip => __('Force a redraw of the entire Chart display.'),
callback => sub { my ($action, $self) = @_;
$self->queue_draw; }
},
{ name => 'Intraday',
label => __('_Intraday'),
tooltip => __p('Main-accelerator-key','<Ctrl>I'),
callback => sub {
my ($action, $self) = @_;
require App::Chart::Gtk2::IntradayDialog;
App::Chart::Gtk2::IntradayDialog->popup ($self->get_symbol, $self);
},
},
{ name => 'Annotations',
label => __('_Annotations'),
callback => sub {
my ($action, $self) = @_;
require App::Chart::Gtk2::AnnotationsDialog;
App::Chart::Gtk2::AnnotationsDialog->popup ($self->get_symbol, $self);
},
},
{ name => 'ViewStyle',
label => __('_View Style'),
callback => sub { my ($action, $self) = @_;
Gtk2::Ex::WidgetCursor->busy;
require App::Chart::Gtk2::ViewStyleDialog;
my $vs = App::Chart::Gtk2::ViewStyleDialog->instance_for_screen($self);
$vs->present;
my $view = $self->{'view'};
$vs->set (view => $view,
viewstyle => $view->get('viewstyle'));
}
},
{ name => 'Raw',
label => __('_Raw data'),
callback => sub { my ($action, $self) = @_;
require App::Chart::Gtk2::RawDialog;
App::Chart::Gtk2::RawDialog->popup ($self->get_symbol, $self); }
},
{ name => "WebMenuItem",
label => __('_Web')
},
# Tools menu
{ name => 'Watchlist',
label => __('_Watchlist'),
callback => sub {
my ($action, $self) = @_;
App::Chart::Gtk2::Ex::ToplevelBits::popup
('App::Chart::Gtk2::WatchlistDialog',
screen => $self,
hide_on_delete => 1);
},
},
{ name => 'Download',
label => __('_Download'),
callback => sub { my ($action, $self) = @_;
require App::Chart::Gtk2::DownloadDialog;
App::Chart::Gtk2::DownloadDialog->popup ($self->get_symbol, $self); }
},
{ name => 'DownloadUpdate',
label => __('Download _Update'),
accelerator => __p('Main-accelerator-key','<Ctrl>U'),
callback => sub {
my ($action, $self) = @_;
# meant to be sensitive only with a symbol, but check anyway
my $symbol = $self->get_symbol || return;
require App::Chart::Gtk2::DownloadDialog;
my $dialog = App::Chart::Gtk2::DownloadDialog->instance_for_screen($self);
my $job = $dialog->start ($symbol, undef);
my $jobmsg = ($self->{'jobmsg'} ||= do {
require App::Chart::Gtk2::JobStatusbarMessage;
App::Chart::Gtk2::JobStatusbarMessage->new
(statusbar => $self->{'statusbar'});
});
$jobmsg->add_job ($job);
} },
{ name => 'History',
label => __('_History'),
tooltip => __('Dialog of back/forward symbols.'),
callback => sub {
my ($action, $self) = @_;
App::Chart::Gtk2::Ex::ToplevelBits::popup
('Gtk2::Ex::History::Dialog',
lib/App/Chart/Gtk2/Main.pm view on Meta::CPAN
# my $actiongroup = shift;
# my $self = $class->new (@_);
# $actiongroup->add_action_with_accel ($self, $self->accelerator);
# }
# sub accelerator {
# my ($self) = @_;
# return ($self->get('way') eq 'back'
# ? __p('accelerator-key','B')
# : __p('accelerator-key','F'));
# }
$actiongroup->add_action_with_accel
(Gtk2::Ex::History::Action->new (name => 'Back',
way => 'back',
history => $history),
__p('accelerator-key-back','B'));
$actiongroup->add_action_with_accel
(Gtk2::Ex::History::Action->new (name => 'Forward',
way => 'forward',
history => $history),
__p('accelerator-key-forward','F'));
# initially nothing
$actiongroup->get_action('AddFavourite')->set_sensitive (0);
$actiongroup->get_action('RemoveFavourite')->set_sensitive (0);
# these actions only sensitive when there's a symbol displayed
$self->{'symbol_sensitive_actions'} = ['AddFavourite', 'RemoveFavourite',
'Delete', 'Centre', 'DownloadUpdate',
'Annotations'];
_do_symbol_changed ($self, ''); # hack for initial insensitive
Gtk2::Ex::ActionTooltips::action_tooltips_to_menuitems_dynamic
($actiongroup->get_action('ManualDataSource'),
$actiongroup->get_action('ManualMovingAverage'),
$actiongroup->get_action('ManualIndicator'));
$actiongroup->add_toggle_actions
# name, stock id, label, accel, tooltip, subr, is_active
([{ name => 'Cross',
label => __('_Cross'),
accelerator => __p('Main-accelerator-key','C'),
tooltip => __('Show a crosshair of horizontal and vertical lines following the mouse pointer.'),
is_active => 0,
callback => sub {
my ($action, $self) = @_;
$self->{'crosshair_connect'} ||= do {
my $cross = $self->{'view'}->crosshair;
Glib::Ex::ConnectProperties->new ([$action,'active'],
[$cross,'active']);
};
},
},
{ name => 'Ticker',
label => __('_Ticker'),
is_active => 0,
tooltip => __('Show a stock ticker of share prices at the bottom of the window.
Mouse button-1 there drags it back or forward. Button-3 pops up a menu of options, including which symbol list it shows.'),
callback => sub {
my ($action, $self) = @_;
Gtk2::Ex::WidgetCursor->busy; # can take a moment to load
$self->get_or_create_ticker;
},
},
{ name => 'Toolbar',
label => __('T_oolbar'),
tooltip => __('Show (or not) the toolbar.'),
is_active => 1,
},
],
$self);
my @timebases = qw(App::Chart::Timebase::Days
App::Chart::Timebase::Weeks
App::Chart::Timebase::Months);
$actiongroup->add_radio_actions
([{ name => 'Daily',
label => __('_Daily'),
accelerator => __p('Main-accelerator-key','<Ctrl>D'),
tooltip => __('Display daily data.'),
value => 0,
},
{ name => 'Weekly',
label =>__('_Weekly'),
accelerator => __p('Main-accelerator-key','<Ctrl>W'),
tooltip => __('Display weekly data.'),
value => 1,
},
{ name => 'Monthly',
label =>__('_Monthly'),
accelerator => __p('Main-accelerator-key','<Ctrl>M'),
tooltip => __('Display monthly data.'),
value => 2,
}],
0, # initial
sub { my ($action, $current_action, $self) = @_;
Gtk2::Ex::WidgetCursor->busy;
$self->{'view'}->set (timebase_class =>
$timebases[$action->get_current_value]);
},
$self);
my $ui = $self->{'ui'} = Gtk2::UIManager->new;
$ui->insert_action_group ($actiongroup, 0);
$self->add_accel_group ($ui->get_accel_group);
$ui->add_ui_from_string (<<'HERE');
<ui>
<menubar name='MenuBar'>
<menu action='FileMenu'>
<menuitem action='Open'/>
<menuitem action='Delete'/>
<menuitem action='AddFavourite'/>
<menuitem action='RemoveFavourite'/>
<separator/>
<menuitem action='Prev'/>
<menuitem action='Next'/>
<menuitem action='Back'/>
<menuitem action='Forward'/>
<separator/>
<menuitem action='Quit'/>
</menu>
<menu action='EditMenu'>
<menuitem action='Annotations'/>
<menuitem action='ViewStyle'/>
<menuitem action='Preferences'/>
<menuitem action='Raw'/>
</menu>
<menu action='ViewMenu'>
<menuitem action='Daily'/>
<menuitem action='Weekly'/>
<menuitem action='Monthly'/>
<separator/>
<menuitem action='ZoomInY'/>
<menuitem action='ZoomOutY'/>
<menuitem action='ZoomInX'/>
<menuitem action='ZoomOutX'/>
<menuitem action='Centre'/>
<menuitem action='Redraw'/>
<separator/>
<menuitem action='Intraday'/>
<menuitem action='WebMenuItem'/>
</menu>
<menu action='ToolsMenu'>
<menuitem action='Download'/>
<menuitem action='DownloadUpdate'/>
<menuitem action='Watchlist'/>
<menuitem action='Cross'/>
<menuitem action='Ticker'/>
<menuitem action='Toolbar'/>
<menuitem action='History'/>
<separator/>
<menuitem action='Vacuum'/>
<menuitem action='Errors'/>
<menuitem action='Diagnostics'/>
</menu>
<menu action='HelpMenu'>
<menuitem action='About'/>
lib/App/Chart/Gtk2/Main.pm view on Meta::CPAN
delete $self->{'history'};
delete $self->{'ui'};
delete $self->{'actiongroup'};
return shift->signal_chain_from_overridden(@_);
# delete $self->{'statusbar'};
# delete $self->{'view'};
# delete $self->{'symbol_sensitive_actions'};
# if (DEBUG) { print " keys left: ", join(',', keys %$self), "\n"; }
# %$self = ();
# print "children ",$self->get_children,"\n";
}
sub shrink_to_aspect_ratio {
my ($width, $height, $ratio) = @_;
$width = min ($width, $ratio * $height);
$height = min ($height, (1.0/$ratio) * $width);
return ($width, $height);
}
sub x_mm_to_pixels {
my ($widget, $x) = @_;
my $screen = $widget->get_screen
|| croak 'x_mm_to_pixels(): widget not on a screen yet';
return $x * $screen->get_width / $screen->get_width_mm;
}
sub y_mm_to_pixels {
my ($widget, $y) = @_;
my $screen = $widget->get_screen
|| croak 'y_mm_to_pixels(): widget not on a screen yet';
return $y * $screen->get_height / $screen->get_height_mm;
}
sub _webmenuitem_submenu {
my ($webitem, $self) = @_;
### _webmenuitem_submenu() have: $webitem->get_submenu
unless ($webitem->get_submenu) {
require App::Chart::Gtk2::WeblinkMenu;
my $webmenu = $self->{'webmenu'} = App::Chart::Gtk2::WeblinkMenu->new
(symbol => $self->{'symbol'});
$webitem->set_submenu ($webmenu);
# gtk 2.18 bug -- set_submenu doesn't notify attach-widget
$webmenu->notify ('attach-widget');
}
}
#------------------------------------------------------------------------------
# broadcast handlers
# 'delete-symbol' broadcast handler
sub _do_delete_symbol {
my ($self, $symbol) = @_;
my $self_symbol = $self->{'symbol'};
### Main delete-symbol: $symbol
### showing: $self_symbol
# when currently displayed symbol is deleted goto next, or if no next
# then previous, or if no previous then go to displaying nothing
if (defined $self_symbol && $self_symbol eq $symbol) {
Gtk2::Ex::WidgetCursor->busy;
($symbol, my $symlist) = $self->smarker->next ('database');
if (! defined $symbol) {
### next is undef
($symbol, $symlist) = $self->smarker->prev ('database');
### prev: $symbol
}
_goto_with_history ($self, $symbol, $symlist);
}
}
#------------------------------------------------------------------------------
# misc
sub get_or_create_ticker {
my ($self) = @_;
return ($self->{'ticker'} ||= do {
require App::Chart::Gtk2::Ticker;
my $ticker = App::Chart::Gtk2::Ticker->new;
$self->{'vbox'}->pack_start ($ticker, 0,0,0);
my $action = $self->{'actiongroup'}->get_action ('Ticker');
Glib::Ex::ConnectProperties->new ([$action,'active'],
[$ticker,'visible']);
$ticker;
});
}
# 'symbol-changed' class closure
sub _do_symbol_changed {
my ($self, $symbol) = @_;
my $sensitive = (defined $symbol && $symbol ne '');
my $actiongroup = $self->{'actiongroup'};
foreach my $name (@{$self->{'symbol_sensitive_actions'}}) {
my $action = $actiongroup->get_action ($name);
$action->set_sensitive ($sensitive);
}
{ my $action = $actiongroup->get_action ('ManualDataSource');
my $node = $symbol && App::Chart::symbol_source_help ($symbol);
$action->set_sensitive ($node);
my $tip = $node && __x('Open the manual at the "{node}" section about this symbol\'s data source', node => $node);
$action->set (tooltip => $tip);
}
{ my $action = $actiongroup->get_action ('ManualMovingAverage');
my $node = manual_for_graph_n($self,0);
$action->set_sensitive ($node);
my $tip = $node && __x('Open the manual at the "{node}" section about this moving average', node => $node);
$action->set (tooltip => $tip);
}
{ my $action = $actiongroup->get_action ('ManualIndicator');
my $node = manual_for_graph_n($self,1);
$action->set_sensitive ($node);
my $tip = $node && __x('Open the manual at the "{node}" section about this indicator', node => $node);
$action->set (tooltip => $tip);
}
}
sub manual_for_graph_n {
my ($self, $n) = @_;
my $view = $self->{'view'};
my $graph = $view->{'graphs'}->[$n] || return;
my $series = (List::Util::first {! $_->isa('App::Chart::Series::Database')}
@{$graph->get('series-list')})
|| return;
my $func = $series->can('manual') || return;
return $series->$func;
}
#------------------------------------------------------------------------------
# navigation
sub symbol_history {
my ($self) = @_;
return $self->{'history'};
}
sub _history_place_to_text {
my ($history, $place) = @_;
require App::Chart::Database;
my ($symbol, $symlist_key) = @$place;
if (defined (my $name = App::Chart::Database->symbol_name ($symbol))) {
$symbol .= " - $name";
}
return $symbol;
}
sub _history_place_to_symbol_symlist {
my ($place) = @_;
my ($symbol, $symlist_key) = @$place;
require App::Chart::Gtk2::Symlist;
my $symlist = App::Chart::Gtk2::Symlist->new_from_key_maybe ($symlist_key);
return ($symbol, $symlist);
}
sub _history_symbol_symlist_to_place {
my ($symbol, $symlist) = @_;
return [ $symbol, $symlist && $symlist->key ];
}
sub _goto {
my ($self, $symbol, $symlist) = @_;
Gtk2::Ex::WidgetCursor->busy;
$self->{'symbol'} = $symbol;
$self->{'symlist'} = $symlist;
$self->{'view'}->set('symbol', $symbol);
if (my $webmenu = $self->{'webmenu'}) { $webmenu->set('symbol', $symbol); }
$self->signal_emit ('symbol-changed', $symbol);
if ($symbol) {
require App::Chart::Gtk2::Job::Latest;
App::Chart::Gtk2::Job::Latest->start_for_view ($symbol, $symlist);
}
}
sub _goto_with_history {
my ($self, $symbol, $symlist) = @_;
### _goto_with_history: $symbol, $symlist && $symlist->key
if ($symbol) {
my $history = $self->symbol_history;
$history->goto (_history_symbol_symlist_to_place ($symbol, $symlist));
}
}
sub _history_notify_current {
my ($history, $pspec, $self) = @_;
_goto ($self, _history_place_to_symbol_symlist($history->get('current')));
}
sub smarker {
my ($self) = @_;
return ($self->{'smarker'} ||= do {
require App::Chart::Gtk2::Smarker;
App::Chart::Gtk2::Smarker->new;
});
}
sub goto_symbol {
my ($self, $symbol, $symlist) = @_;
### Main goto: $symbol, $symlist && $symlist->key
_goto_with_history ($self, $symbol, $symlist);
$self->smarker->goto ($symbol, $symlist);
}
sub goto_next {
my ($self) = @_;
Gtk2::Ex::WidgetCursor->busy;
my ($symbol, $symlist) = $self->smarker->next ('database');
# require App::Chart::Gtk2::Symlist;
# my ($symbol, $symlist)
# = App::Chart::Gtk2::Symlist::next ($self->{'symbol'}, $self->{'symlist'});
if ($symbol) {
_goto_with_history ($self, $symbol, $symlist);
} else {
_message ($self, __('At end of lists'));
}
}
sub go_prev {
my ($self) = @_;
Gtk2::Ex::WidgetCursor->busy;
my ($symbol, $symlist) = $self->smarker->prev ('database');
# require App::Chart::Gtk2::Symlist;
# my ($symbol, $symlist)
# = App::Chart::Gtk2::Symlist::previous ($self->{'symbol'}, $self->{'symlist'});
if ($symbol) {
_goto_with_history ($self, $symbol, $symlist);
} else {
_message ($self, __('At start of lists'));
}
}
sub go_back {
my ($self) = @_;
$self->symbol_history->back;
}
sub go_forward {
my ($self) = @_;
$self->symbol_history->forward;
}
#------------------------------------------------------------------------------
# other
sub _message {
my ($self, $str) = @_;
require Gtk2::Ex::Statusbar::MessageUntilKey;
Gtk2::Ex::Statusbar::MessageUntilKey->message ($self->{'statusbar'}, $str);
}
# return currently displayed symbol, or undef
sub get_symbol {
my ($self) = @_;
return $self->{'view'}->get('symbol');
}
# return the menubar widget
sub menubar {
my ($self) = @_;
return $self->{'ui'}->get_widget('/MenuBar');
}
# return App::Chart::Gtk2::Main widget, preferring the transient parent of $dialog,
# if $dialog is given
sub find_for_dialog {
my ($class, $dialog) = @_;
if ($dialog
&& $dialog->can('get_transient_for')
&& (my $parent = $dialog->get_transient_for)) {
if ($parent->isa($class)) {
return $parent;
}
}
my $screen = $dialog->get_screen;
foreach my $toplevel (Gtk2::Window->list_toplevels) {
if ($toplevel->isa($class) && $toplevel->get_screen == $screen) {
return $toplevel;
}
}
( run in 0.518 second using v1.01-cache-2.11-cpan-483215c6ad5 )