App-Chart

 view release on metacpan or  search on metacpan

lib/App/Chart/Gtk2/IntradayImage.pm  view on Meta::CPAN

                 ('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
    $self->queue_resize;
    $self->queue_draw;
  }
}

# 'size-request' class closure
sub _do_size_request {
  my ($self, $req) = @_;
  ### IntradayImage _do_size_request()
  my $pixbuf = _load_pixbuf ($self);
  if (ref $pixbuf) {
    $req->width ($pixbuf->get_width);
    $req->height ($pixbuf->get_height);
  } else {
    $req->width (35 * Gtk2::Ex::Units::em($self));
    $req->height (6 * Gtk2::Ex::Units::line_height($self));
  }
  ### _do_size_request() decide: $req->width."x".$req->height
}

# 'expose-event' class closure
sub _do_expose_event {
  my ($self, $event) = @_;
  ### IntradayImage _do_expose_event(): $self->get_name.' "'.($self->{'symbol'}||'[nosymbol]').'" "'.($self->{'mode'}||'[nomode]').'"'
  my $win = $self->window;

  # Reading the database on every expose probably isn't fast, but we're not
  # expecting to scroll or anything much, so leaving the data on disk might
  # save a little memory.
  #
  my $pixbuf = _load_pixbuf ($self);
  if (! ref $pixbuf) {
    my $errmsg = $pixbuf;
    ### pixbuf load error: $errmsg
    $win->clear;
    App::Chart::Gtk2::GUI::draw_text_centred ($self, undef, $errmsg);
    return Gtk2::EVENT_PROPAGATE;
  }

  my $pix_width  = $pixbuf->get_width;
  my $pix_height = $pixbuf->get_height;
  ### pixbuf: "${pix_width}x${pix_height}"

  my ($x, $y, $alloc_width, $alloc_height) = $self->allocation->values;
  ### alloc size: "${alloc_width}x${alloc_height} at $x,$y"

  # windowed
  $x = 0; $y = 0;

  # align in allocated space, if alloc bigger than pixbuf
  my $x_offset = max(0, ($alloc_width - $pix_width) / 2);
  my $y_offset = max(0, ($alloc_height - $pix_height) / 2);

  # 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 {



( run in 0.839 second using v1.01-cache-2.11-cpan-39bf76dae61 )