Gtk2-Ex-Graph-GD

 view release on metacpan or  search on metacpan

lib/Gtk2/Ex/Graph/GD.pm  view on Meta::CPAN

}

sub signal_connect {
	my ($self, $signal, $callback) = @_;
	$self->{signals}->{$signal} = $callback;
}

sub _create_eventbox {
	my ($self) = @_;
	my $eventbox = Gtk2::EventBox->new;
	# $eventbox->add_events (['pointer-motion-mask', 'pointer-motion-hint-mask', 'button-press-mask']);
	$eventbox->add_events ('pointer-motion-mask');
	$eventbox->signal_connect ('motion-notify-event' => 
		sub {
			my ($widget, $event) = @_;
			my ($x, $y) = ($event->x, $event->y);
			my @imageallocatedsize = $self->{graphimage}->allocation->values;
			$x -= ($imageallocatedsize[2] - $self->{imagesize}->[0])/2;
			$y -= ($imageallocatedsize[3] - $self->{imagesize}->[1])/2;
			if ($self->{graphtype} eq 'bars') {
				my $hotspot = $self->_check_bars_hotspot($x,$y);
				if ($hotspot) {
					my ($measure, $xvalue, $yvalue) = @$hotspot;
					my $tooltipstring = $measure 
						? "($measure, $xvalue, $yvalue)" 
						: "($xvalue, $yvalue)";
					$self->_show_tooltip($tooltipstring);
					&{ $self->{signals}->{'mouse-over'} } ($hotspot)
							if $self->{signals}->{'mouse-over'};
				}
			} elsif ($self->{graphtype} eq 'lines' or $self->{graphtype} eq 'linespoints') {
				my $hotspot = $self->_check_lines_hotspot($x,$y);
				if ($hotspot) {
					my ($measure, $xvalue0, $yvalue0, $xvalue1, $yvalue1) = @$hotspot;
					my $tooltipstring = $measure 
						? "($measure, ($xvalue0, $yvalue0), ($xvalue1, $yvalue1))"
						: "(($xvalue0, $yvalue0), ($xvalue1, $yvalue1))";
					$self->_show_tooltip($tooltipstring);
					&{ $self->{signals}->{'mouse-over'} } ($hotspot)
							if $self->{signals}->{'mouse-over'};
				}
			}
		}
	);
	$eventbox->signal_connect ('button-press-event' => 
		sub {
			my ($widget, $event) = @_;
			my ($x, $y) = ($event->x, $event->y);
			my @imageallocatedsize = $self->{graphimage}->allocation->values;
			$x -= ($imageallocatedsize[2] - $self->{imagesize}->[0])/2;
			$y -= ($imageallocatedsize[3] - $self->{imagesize}->[1])/2;
			my $hotspot;
			if ($self->{graphtype} eq 'bars') {
				$hotspot = $self->_check_bars_hotspot($x,$y);
			} elsif ($self->{graphtype} eq 'lines' or $self->{graphtype} eq 'linespoints') {
				$hotspot = $self->_check_lines_hotspot($x,$y);
			}
			&{ $self->{signals}->{'clicked'} } ($hotspot)
					if $self->{signals}->{'clicked'} && $hotspot;
			return FALSE unless $event->button == 3;
			$self->{optionsmenu}->popup(
				undef, # parent menu shell
				undef, # parent menu item
				undef, # menu pos func
				undef, # data
				$event->button,
				$event->time
			);
		}
	);
	return $eventbox;
}

sub set {
	my ($self, %hash) = @_;
	$self->{graphhash} = \%hash;
	$self->{graph}->set(%hash);
}

sub _set_type {
	my ($self, $type) = @_;
	my ($width, $height) = @{$self->{imagesize}};
	$self->{graphtype} = $type;
	my $graph;
	if ($type eq 'bars') {
		$graph = GD::Graph::bars->new($width, $height);
	} elsif ($type eq 'lines') {
		$graph = GD::Graph::lines->new($width, $height);
	} elsif ($type eq 'linespoints') {
		$graph = GD::Graph::linespoints->new($width, $height);
	} elsif ($type eq 'area') {
		$graph = GD::Graph::area->new($width, $height);
	} elsif ($type eq 'pie') {
		$graph = GD::Graph::pie->new($width, $height);
	}
	$self->{graph} = undef;
	$self->{graph} = $graph;
}

sub _refresh {
	my ($self) = @_;
	$self->{graph}->set(%{$self->{graphhash}}) if $self->{graphhash};
	$self->set_legend(@{$self->{graphlegend}}) if $#{@{$self->{graphlegend}}} >= 0;
	$self->get_image($self->{graphdata});
}

sub _init_tooltip {
	my ($self) = @_;
	my $tooltip_label = Gtk2::Label->new;
	my $tooltip = Gtk2::Window->new('popup');
	$tooltip->set_decorated(0);
	$tooltip->set_position('mouse'); # We'll choose this to start with.
	$tooltip->modify_bg ('normal', Gtk2::Gdk::Color->parse('yellow')); # The obligatory yellow
	$tooltip->add($tooltip_label);
	$self->{tooltip}->{window} = $tooltip;
	$self->{tooltip}->{displayed} = FALSE;
	$self->{tooltip}->{label} = $tooltip_label;	
}

sub set_legend {
	my ($self, @legend_keys) = @_;
	return if ($self->{graphtype} eq 'pie');
	$self->{graph}->set_legend(@legend_keys);
	$self->{graphlegend} = \@legend_keys;
}

sub get_image {
	my ($self, $data) = @_;
	$self->{graphdata} = $data;
	my $graph = $self->{graph};
	$graph->plot($data) or warn $graph->error;
	my $loader = Gtk2::Gdk::PixbufLoader->new;
	$loader->write ($graph->gd->png);
	$loader->close;
	my $image = Gtk2::Image->new_from_pixbuf($loader->get_pixbuf);
	$self->{graphimage} = $image;
	my $hotspotlist;
	if ($self->{graphtype} eq 'bars' or
		$self->{graphtype} eq 'lines' or
		$self->{graphtype} eq 'linespoints') {
		foreach my $hotspot ($graph->get_hotspot) {
			push @$hotspotlist, $hotspot if $hotspot;
		}
	}
	$self->{hotspotlist} = $hotspotlist;
	my $eventbox = $self->{eventbox};
	my @children = $eventbox->get_children;
	foreach my $child (@children) {
		$eventbox->remove($child);
	}
	$eventbox->add ($image);

	$eventbox->signal_connect ('button-press-event' => 
		sub {
			my ($widget, $event) = @_;
			return TRUE;
			return FALSE unless $event->button == 3;
			$self->{optionsmenu}->popup(
				undef, # parent menu shell
				undef, # parent menu item
				undef, # menu pos func
				undef, # data
				$event->button,
				$event->time
			);
		}
	);	
	$eventbox->show_all;
	return $eventbox;
}

sub _show_tooltip {
	my ($self, $tooltipstring) = @_;
	$self->{tooltip}->{label}->set_label($tooltipstring);
	if (!$self->{tooltip}->{displayed}) {
		$self->{tooltip}->{window}->show_all;
		my ($thisx, $thisy) = $self->{tooltip}->{window}->window->get_origin;
		# I want the window to be a bit away from the mouse pointer.
		# Just a personal choice
		$self->{tooltip}->{window}->move($thisx, $thisy-20);
		$self->{tooltip}->{displayed} = TRUE;
	}	
}

sub _check_lines_hotspot {
	my ($self, $x, $y) = @_;
	my $i=0;
	my $hotspotlist = $self->{hotspotlist};
	foreach my $datameasure (@$hotspotlist){
		my $j=0;
		foreach my $hotspot (@$datameasure) {
			my ($name, @coords) = @$hotspot;
			if (_on_the_line($x, $y, @coords)) {
				my $xvalue0 = $self->{graphdata}->[0]->[$j-1];
				my $yvalue0 = $self->{graphdata}->[$i+1]->[$j-1];
				my $xvalue1 = $self->{graphdata}->[0]->[$j];
				my $yvalue1 = $self->{graphdata}->[$i+1]->[$j];
				my $measure = $self->{graphlegend}->[$i];
				return [$measure, $xvalue0, $yvalue0, $xvalue1, $yvalue1];
			}
			$j++;
		} 
		$i++;	
	}
	$self->{tooltip}->{window}->hide;
	$self->{tooltip}->{displayed} = FALSE;
}

sub _on_the_line {
	my ($x, $y, @linecoords) = @_;
	if (($x <= $linecoords[0] and  $x <= $linecoords[2]) or
		($x >= $linecoords[0] and  $x >= $linecoords[2]) or
		($y <= $linecoords[1] and  $y <= $linecoords[3]) or
		($y >= $linecoords[1] and  $y >= $linecoords[3]) ){
		return FALSE;
	}
	my $slope_diff = 
		($linecoords[1]-$linecoords[3])/($linecoords[0]-$linecoords[2]) 



( run in 2.185 seconds using v1.01-cache-2.11-cpan-364913b4093 )