App-Chart
view release on metacpan or search on metacpan
lib/App/Chart/Gtk2/IntradayImage.pm view on Meta::CPAN
# Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2014, 2016, 2018 Kevin Ryde
# This file is part of Chart.
#
# Chart is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3, or (at your option) any later version.
#
# Chart is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with Chart. If not, see <http://www.gnu.org/licenses/>.
package App::Chart::Gtk2::IntradayImage;
use 5.010;
use strict;
use warnings;
use Carp;
use Gtk2 1.220;
use Encode;
use Encode::Locale; # for coding system "locale"
use List::Util qw(min max);
use Locale::TextDomain ('App-Chart');
use Gtk2::Ex::Units;
use Gtk2::Ex::PixbufBits;
use App::Chart::Database;
use App::Chart::Gtk2::GUI;
# uncomment this to run the ### lines
# use Smart::Comments;
use Glib::Object::Subclass
'Gtk2::DrawingArea',
signals => { expose_event => \&_do_expose_event,
size_request => \&_do_size_request },
properties => [Glib::ParamSpec->string
('symbol',
__('Symbol'),
'The symbol of the stock or commodity to be shown.',
'', # default
Glib::G_PARAM_READWRITE),
Glib::ParamSpec->string
('mode',
'Mode',
'The intraday mode, such as "1d" for one day. The possible values here depend on the symbol\'s data source code.',
'', # default
Glib::G_PARAM_READWRITE)];
sub INIT_INSTANCE {
my ($self) = @_;
$self->{'symbol'} = '';
$self->{'mode'} = '';
# Single pixbuf draw operation doesn't need double buffering.
$self->set_double_buffered (0);
$self->set_app_paintable (1);
App::Chart::chart_dirbroadcast()->connect_for_object
('intraday-changed', \&_do_intraday_changed, $self);
}
sub SET_PROPERTY {
my ($self, $pspec, $newval) = @_;
my $pname = $pspec->get_name;
### IntradayImage SET_PROPERTY(): "$pname $newval"
my $oldval = $self->{$pname};
$self->{$pname} = $newval; # per default GET_PROPERTY
### stored to: ''.\$self->{$pname}
if ($oldval eq $newval) {
return;
}
if ($pname eq 'symbol' || $pname eq 'mode') {
# new image (or new no image)
delete $self->{'xor_background'}; # new colour scheme
lib/App/Chart/Gtk2/IntradayImage.pm view on Meta::CPAN
# restrict to alloc width/height, in case pixbuf+pad is bigger than alloc
my $width = min ($alloc_width - $x_offset, $pix_width);
my $height = min ($alloc_height - $y_offset, $pix_height);
my $gc = $self->get_style->bg_gc($self->state);
$gc->set_clip_region ($event->region);
$win->draw_pixbuf ($gc, $pixbuf,
0, 0, # source x,y
$x+$x_offset, $y+$y_offset, # dest x,y
$width, $height,
'normal', # dither
0, 0); # dither x,y
my $region = $event->region->copy;
$region->subtract (Gtk2::Gdk::Region->rectangle
(Gtk2::Gdk::Rectangle->new
($x+$x_offset, $y+$y_offset, $width, $height)));
$gc->set_clip_region ($region);
$win->draw_rectangle ($gc, 1, $event->area->values);
$gc->set_clip_region (undef);
return Gtk2::EVENT_PROPAGATE;
}
sub _load_pixbuf {
my ($self) = @_;
### _load_pixbuf() ...
my $symbol = $self->{'symbol'};
my $mode = $self->{'mode'};
if (! $symbol || ! $mode) { return __('(No data)'); }
my $dbh = App::Chart::DBI->instance;
my $sth = $dbh->prepare_cached
('SELECT image, error FROM intraday_image WHERE symbol=? AND mode=?');
# Crib note: Some DBI 1.618 SQLite3 1.35 seems to hold a ref to the
# scalars passed to selectrow_array() until the next call. So use the
# local variables since holding onto $self->{'symbol'} looks like a leak.
#
my ($image, $error) = $dbh->selectrow_array ($sth, undef,
$symbol,
$mode);
$sth->finish();
if (! defined $image) { # error message in database
return $error || __('(No data)');
}
my $loader = Gtk2::Gdk::PixbufLoader->new();
my $pixbuf;
if (eval {
$loader->write ($image);
$loader->close ();
$pixbuf = $loader->get_pixbuf;
1 }) {
return $pixbuf;
} else {
# Should be Glib::Error in $@ thrown by $loader, but allow for plain
# string too.
my $err = "$@";
unless (utf8::is_utf8($err)) { $err = Encode::decode('locale',$err); }
return $err;
}
}
sub _do_intraday_changed {
my ($self, $symbol, $mode) = @_;
### IntradayImage _do_intraday_changed(): "\"$symbol\" \"$mode\"\n"
if ($self->{'symbol'} eq $symbol && $self->{'mode'} eq $mode) {
# new image (or new no image)
delete $self->{'xor_background'}; # new colour scheme
$self->queue_resize;
$self->queue_draw;
}
}
#-----------------------------------------------------------------------------
# pixbuf background
sub Gtk2_Ex_Xor_background {
my ($self) = @_;
return ($self->{'xor_background'} ||= do {
require Gtk2::Ex::PixbufBits;
my $pixbuf = _load_pixbuf ($self);
if (! ref $pixbuf) {
# error loading, treat as widget background
return $self->get_style->bg($self->state);
}
my $rgbstr = Gtk2::Ex::PixbufBits::sampled_majority_color ($pixbuf);
### IntradayImage xor background: $rgbstr
require App::Chart::Gtk2::Ex::GdkColorAlloc;
App::Chart::Gtk2::Ex::GdkColorAlloc->new (widget => $self,
color => $rgbstr);
});
}
1;
__END__
=for stopwords intraday PNG JPEG GIF
=head1 NAME
App::Chart::Gtk2::IntradayImage -- intraday image display widget
=head1 SYNOPSIS
my $image = App::Chart::Gtk2::IntradayImage->new;
$image->set (symbol => 'BHP.AX',
mode => '1d');
=head1 WIDGET HIERARCHY
C<App::Chart::Gtk2::IntradayImage> is a subclass of C<Gtk2::DrawingArea>.
Gtk2::Widget
Gtk2::DrawingArea
App::Chart::Gtk2::IntradayImage
=head1 DESCRIPTION
( run in 0.861 second using v1.01-cache-2.11-cpan-ceb78f64989 )