App-Chart

 view release on metacpan or  search on metacpan

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

                                ],
                },
              ],
  };

sub viewstyle_read {
  require App::Chart::DBI;
  my $str = App::Chart::DBI->read_single
    ('SELECT value FROM preference WHERE key=\'viewstyle\'');
  if (! defined $str) { return DEFAULT_VIEWSTYLE; }
  my $viewstyle = eval $str;
  if (! defined $viewstyle) {
    print "chart: oops, bad viewstyle in database, using default: $@";
    return DEFAULT_VIEWSTYLE;
  }
 return $viewstyle;
}
# viewstyle_write(DEFAULT_VIEWSTYLE);
# print viewstyle_read(DEFAULT_VIEWSTYLE);
# exit 0;
sub viewstyle_write {
  my ($viewstyle) = @_;
  require App::Chart::DBI;
  require Data::Dumper;
  my $str = Data::Dumper->new([$viewstyle],['viewstyle'])->Indent(1)->Terse(1)->Sortkeys(1)->Dump;
  require App::Chart::DBI;
  my $dbh = App::Chart::DBI->instance;
  $dbh->do ('INSERT OR REPLACE INTO preference (key, value)
             VALUES (\'viewstyle\',?)', {}, $str);
  App::Chart::chart_dirbroadcast()->send ('viewstyle-changed');
}

#------------------------------------------------------------------------------

sub INIT_INSTANCE {
  my ($self) = @_;
  $self->{'symbol'} = '';  # per property default above
  $self->{'series_list'} = [];
  $self->{'timebase_class'} = DEFAULT_TIMEBASE_CLASS;
  $self->{'graphs'} = [];
  $self->set(n_rows => 9,
             n_columns => 3);

  App::Chart::chart_dirbroadcast()->connect_for_object
      ('data-changed', \&_do_data_changed, $self);

  # FIXME: this induces a rescale at a good time, but otherwise not wanted
  App::Chart::chart_dirbroadcast()->connect_for_object
      ('latest-changed', \&_do_data_changed, $self);

  App::Chart::Gtk2::GUI::chart_style_widget ('AppChartViewLabel');
  my $ebox = $self->{'initial'} = Gtk2::EventBox->new;
  $ebox->set_name ('AppChartViewLabel');
  my $label = Gtk2::Label->new
    (__('Use File/Open to open or add a symbol'));
  $label->set_name ('AppChartViewLabel');
  $ebox->add ($label);
  $ebox->show_all;

  $self->attach ($ebox, 0,3, 0,9,
                 ['fill','shrink','expand'],
                 ['fill','shrink','expand'], 0,0);
}

sub GET_PROPERTY {
  my ($self, $pspec) = @_;
  my $pname = $pspec->get_name;
  if ($pname eq 'viewstyle') {
    if (! $self->{'init_graphs'}) {
      return viewstyle_read();
    }
  }
  return $self->{$pname};
}

sub SET_PROPERTY {
  my ($self, $pspec, $newval) = @_;
  my $pname = $pspec->get_name;
  my $oldval = $self->{$pname};
  ### View SET_PROPERTY: $pname
  ### $newval

  if ($pname eq 'symbol') {
    $self->set_symbol ($newval);
    return;
  }

  $self->{$pname} = $newval;  # per default GET_PROPERTY

  if ($pname eq 'timebase_class') {
    if ($oldval ne $newval) {
      $self->set_symbol ($self->get('symbol'));
    }

  } elsif ($pname eq 'statusbar') {
    # lose old id
    delete $self->{'crosshair_status_id'};

  } elsif ($pname eq 'viewstyle') {
    if ($self->{'init_graphs'}) {
      _update_attach ($self);
    }
    if ($self->{'symbol'}) {
      _set_symbol ($self, $self->{'symbol'});
    }
  }
}

#------------------------------------------------------------------------------
# Crosshair

sub crosshair {
  my ($self) = @_;
  return ($self->{'crosshair_object'}
          ||= do {
            _init_graphs ($self);
            require Gtk2::Ex::CrossHair;
            my $ch = Gtk2::Ex::CrossHair->new (widgets => $self->{'graphs'},
                                               foreground => 'orange');
            $ch->signal_connect (moved => \&_do_crosshair_moved,
                                App::Chart::Glib::Ex::MoreUtils::ref_weak($self));
            ### View created crosshair: "$ch"

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

  $self->{'init_graphs'} = 1;
  $self->{'viewstyle'} = viewstyle_read();

  require App::Chart::Gtk2::Graph;
  require App::Chart::Gtk2::HAxis;

  App::Chart::Gtk2::GUI::chart_style_class ('Gtk2::Ex::NumAxis');

  require App::Chart::Gtk2::Heading;
  $self->{'heading'} = App::Chart::Gtk2::Heading->new;

  # initial horiz scale 4 pixels per date
  require App::Chart::Gtk2::HScale;
  my $hadj = $self->{'hadjustment'}
    = App::Chart::Gtk2::HScale->new (pixel_per_value => 4);
  $self->{'haxis'}   = App::Chart::Gtk2::HAxis->new (adjustment => $hadj);
  $self->{'hscroll'} = Gtk2::HScrollbar->new ($hadj);

  _update_attach ($self);
  $self->show_all;

  #   # this is a nasty hack to force the Gtk2::Table to set its childrens'
  #   # sizes now, instead of later under the queue_resize or whatever
  #   $self->size_allocate ($self->allocation);

  if (my $ebox = delete $self->{'initial'}) {
    $self->remove ($ebox);
  }
}

#   0              1  2  3
# 0 +--------------+--+--+
#   | heading            |
# 1 +--------------+--+--+
#   |              |v |v |
#   | upper        |a |s |
#   |              |x |c |
#   |              |i |r |
#   |              |s |o |
#   |              |  |l |
#   |              |  |l |
# 5 +--------------+--+--+
#   | gap                |
# 6 +--------------+--+--+
#   |              |v |v |
#   | lower        |a |s |
#   |              |x |b |
# 7 +--------------+--+--+
#   | haxis        |     |
# 8 +--------------+     |
#   | hscroll      |     |
# 9 +--------------+--+--+
#
sub _update_attach {
  my ($self) = @_;
  require Gtk2::Ex::TableBits;

  my $y = 0;
  Gtk2::Ex::TableBits::update_attach
      ($self, $self->{'heading'}, 0,3, $y,$y+1,
       ['fill','shrink','expand'], [], 0,0);
  $y++;

  my $graphs = $self->{'graphs'};
  my @graphstyles = @{$self->{'viewstyle'}->{'graphs'}};
  while ($#$graphs > max (0, $#graphstyles)) {
    my $graph = pop @$graphs;
    $self->remove ($graph);
    $self->remove ($graph->{'noshrink'});
    $self->remove ($graph->{'vscroll'});
  }
  $graphs->[0] ||= do {
    my $upper = _make_graph($self);
    delete $upper->{'heading_in_graph'};
    $self->{'hadjustment'}->set (widget => $upper);
    Glib::Ex::ConnectProperties->new ([$upper,'series-list'],
                                      [$self->{'heading'},'series-list']);
    $upper;
  };

  for (my $i = 0; $i < @graphstyles; $i++) {
    my $graph = ($graphs->[$i] ||= _make_graph($self));
    ### now graphs: "@$graphs"

    if ($i > 0) {
      my $gap = ($graph->{'gap'} ||= Glib::Object::new ('Gtk2::DrawingArea',
                                                        height_request => 2));
      Gtk2::Ex::TableBits::update_attach
          ($self, $gap, 0,3, $y,$y+1,
           [], [], 0,0);
      $y++;
    }

    my $graphstyle = $graphstyles[$i];
    my $size = $graphstyle->{'size'};

    Gtk2::Ex::TableBits::update_attach
        ($self, $graph, 0,1, $y,$y+$size,
         ['fill','shrink','expand'],
         ['fill','shrink','expand'], 0,0);
    Gtk2::Ex::TableBits::update_attach
        ($self, $graph->{'noshrink'},
         1,2, $y,$y+$size,
         ['fill','shrink'],
         ['fill','shrink','expand'], 0,0);
    Gtk2::Ex::TableBits::update_attach
        ($self, $graph->{'vscroll'},
         2,3, $y,$y+$size,
         ['fill','shrink'],
         ['fill','shrink','expand'], 0,0);
    $y += $size;
  }

  Gtk2::Ex::TableBits::update_attach
      ($self, $self->{'haxis'}, 0,1, $y,$y+1,
       ['fill','shrink','expand'],
       ['fill','shrink'], 0,0);
  $y++;
  Gtk2::Ex::TableBits::update_attach
      ($self, $self->{'hscroll'}, 0,1, $y,$y+1,
       ['fill','shrink','expand'],
       ['fill','shrink'], 0,0);
  $y++;

  if (my $cross = $self->{'crosshair_object'}) {
    ### _update_attach() cross widgets: "@$graphs"
    $cross->set (widgets => $graphs);
  }

  $self->resize (3, $y);
}

sub _make_graph {
  my ($self) = @_;

  require App::Chart::Gtk2::Graph;
  require App::Chart::Gtk2::AdjScale;
  my $vadj = App::Chart::Gtk2::AdjScale->new (orientation => 'vertical',
                                        inverted => 1);
  my $graph = App::Chart::Gtk2::Graph->new (hadjustment => $self->{'hadjustment'},
                                      vadjustment => $vadj);
  $graph->{'heading_in_graph'} = 1;
  $vadj->set (widget => $graph);
  $graph->signal_connect (button_press_event => \&_do_graph_button_press);

  require Gtk2::Ex::NumAxis;
  my $vaxis = $graph->{'vaxis'}
    = Gtk2::Ex::NumAxis->new (adjustment => $vadj,
                              inverted   => 1);
  $vaxis->signal_connect (number_to_text => \&_vaxis_number_to_text);

  require Gtk2::Ex::NoShrink;
  $graph->{'noshrink'} = Gtk2::Ex::NoShrink->new (child => $vaxis);
  my $vscroll = $graph->{'vscroll'} = Gtk2::VScrollbar->new ($vadj);
  $vscroll->set_inverted (1);

  $vaxis->add_events (['button-press-mask',
                       'button-motion-mask',
                       'button-release-mask']);
  $vaxis->signal_connect (button_press_event => \&_do_vaxis_button_press);
  $graph->show_all;
  return $graph;
}

sub _vaxis_number_to_text {
  my ($axis, $number, $decimals) = @_;
  return App::Chart::number_formatter()->format_number ($number, $decimals, 1);
}


sub _do_vaxis_button_press {
  my ($vaxis, $event) = @_;
  if ($event->button == 1) {
    require Gtk2::Ex::Dragger;
    my $dragger = ($vaxis->{'dragger'} ||=
                   Gtk2::Ex::Dragger->new
                   (widget      => $vaxis,
                    vadjustment => $vaxis->get('adjustment'),
                    vinverted   => 1,
                    cursor      => 'sb-v-double-arrow',
                    confine     => 1));



( run in 0.478 second using v1.01-cache-2.11-cpan-5623c5533a1 )