Gtk2-Ex-VolumeButton

 view release on metacpan or  search on metacpan

lib/Gtk2/Ex/VolumeButton.pm  view on Meta::CPAN

				'min_image',
				'Min Image',
				'Image to display when the volume is minimal',
				'',
				[qw( readable writable )]
		),
		Glib::ParamSpec->string(
				'medium_image',
				'Medium Image',
				'Image to display when the volume is medium',
				'',
				[qw( readable writable )]
		),
		Glib::ParamSpec->string(
				'max_image',
				'Max Image',
				'Image to display when the volume is maximal',
				'',
				[qw( readable writable )]
		),
		Glib::ParamSpec->int(
				'icon_size',
				'Icon Size',
				'Size of the icons',
				0,
				1000,
				18,
				[qw( readable writable )]
		),
		Glib::ParamSpec->string(
				'position',
				'Position',
				'Position of the popup window',
				'bottom',
				[qw( readable writable )]
		),
		Glib::ParamSpec->boolean(
				'muted',
				'Muted',
				'Is the volume muted?',
				0,
				[qw( readable writable )]
		)
	];

sub INIT_INSTANCE {
	my $self = shift;

	$self->{volume} = 0;
	$self->{icon_size} = 18;
	$self->{position} = 'buttom';
	
	$self->signal_connect( 'toggled', \&toggle_cb );
	$self->signal_connect( 'scroll_event', \&scroll_event_cb );

	$self->{image} = Gtk2::Image->new();
	$self->{image}->show();
	$self->add( $self->{image} );
}

sub update_pixbufs {
	my $self = shift;

	for(qw( mute zero min medium max )) {
		if( ref $self->{$_.'_image'} && $self->{$_.'_image'}->isa('Gtk2::Gdk::Pixbuf') ) {
			$self->{pixbufs}->{$_} = $self->{$_.'_image'};
		} elsif( -r $self->{$_.'_image'} ) {
			$self->{pixbufs}->{$_} = Gtk2::Gdk::Pixbuf->new_from_file_at_size( $self->{$_.'_image'}, $self->{icon_size}, $self->{icon_size} );
		} elsif($_) {
			$self->{pixbufs}->{$_} = $self->render_icon( $self->{$_.'_image'}, $self->{icon_size} );
		}
	}
}

sub on_show {
	my $self = shift;
	$self->update_pixbufs();
	$self->update_image( $self->{volume} );
	$self->signal_chain_from_overridden();
}

sub _CLAMP {
	my( $x, $min, $max ) = @_;

	return $max if $x > $max;
	return $min if $x < $min;
	return $x;
}

sub _MAX {
	my( $a, $b ) = @_;

	return ($a > $b) ? $a : $b;
}

sub scale_key_press_cb {
	my( undef, $event, $self ) = @_;

	if( $event->keyval == $Gtk2::Gdk::Keysyms{Escape} ) {
		$self->hide_scale();
		$self->set_volume( $self->{revert_volume} );
		return TRUE;
	} elsif($event->keyval == $Gtk2::Gdk::Keysyms{Return} ||
			$event->keyval == $Gtk2::Gdk::Keysyms{space} ) {
		$self->hide_scale();
		return TRUE;
	}

	return FALSE;
}

sub scale_value_changed_cb {
	my( $widget, $self ) = @_;
	
	my $vol = $widget->get_value();
	$vol = _CLAMP( $vol, 0, 100 );

	$self->{volume} = $vol;
	$self->update_image($vol);

	$self->signal_emit( 'volume_changed', $vol );

lib/Gtk2/Ex/VolumeButton.pm  view on Meta::CPAN

		$self->{popup}->destroy();
	}
}

sub hide_scale {
	my $self = shift;

	if( $self->{popup} ) {
		Gtk2->grab_remove( $self->{popup} );
		Gtk2::Gdk->pointer_ungrab( Gtk2->get_current_event_time() );
		Gtk2::Gdk->keyboard_ungrab( Gtk2->get_current_event_time() );
		$self->{popup}->destroy();
	}

	if( $self->get_active() ) {
		$self->set_active(FALSE);
	}
}

sub toggle_cb {
	my $self = shift;

	if( $self->get_active() ) {
		$self->show_scale();
	} else {
		$self->hide_scale();
	}
}

sub scroll_event_cb {
	my($self, $event) = @_;

	my $vol = $self->{volume};

	if( $event->direction eq 'up' ) {
		$vol += 10;
	} elsif( $event->direction eq 'down' ) {
		$vol -= 10;
	} else {
		return;
	}

	$vol = _CLAMP( $vol, 0, 100 );

	$self->set_volume($vol);
	$self->update_image($vol);
	
	return TRUE;
}

sub set_volume {
	my($self, $vol) = @_;

	return if $self->{volume} == $vol;

	$self->{volume} = $vol;
	$self->update_image( $vol );
	$self->signal_emit( 'volume_changed', $vol );
}

sub update_image {
	my($self, $vol) = @_;
	my $id;
	
	$vol = $self->{volume} unless defined $vol;

	if( $vol <= 0 ) {
		$id = 'zero';
	} elsif( $vol <= 100 / 3 ) {
		$id = 'min';
	} elsif( $vol <= 2 * 100 / 3 ) {
		$id = 'medium';
	} else {
		$id = 'max';
	}

	my $pixbuf = $self->{pixbufs}->{$id}->copy();

	if( $self->{muted} ) {
		$self->{pixbufs}->{mute}->composite(
				$pixbuf,
				0,
				0,
				$self->{pixbufs}->{mute}->get_width(),
				$self->{pixbufs}->{mute}->get_height(),
				0,
				0,
				1.0,
				1.0,
				'bilinear',
				255
		);
	}

	$self->{image}->set_from_pixbuf( $pixbuf );
}

sub toggle_mute {
	my $self = shift;

	$self->{muted} = ($self->{muted}) ? 0 : 1;
	$self->signal_emit( 'mute_changed', $self->{muted} );

	$self->update_image();
}

1;

__END__

=head1 NAME

Gtk2::Ex::VolumeButton - widget to control volume and similar values

=head1 DESCRIPTION

Gtk2::Ex::VolumeButton is a simple Gtk2 widget based on Gtk2::ToggleButton to
control the volume and similar values. It consists of a Gtk2::ToggleButton
widget displaying an image representing the current volume. When the button is
clicked a popup window containing a Gtk2::VScale widget shows up and allows you
to change the widgets volume value. It's also possible to change the volume



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