Re: EXTERNAL: Re: Gtk2::SpinButton For Hex
- From: Juergen Harms <juergen harms unige ch>
- To: <gtk-perl-list gnome org>
- Subject: Re: EXTERNAL: Re: Gtk2::SpinButton For Hex
- Date: Fri, 22 May 2015 21:08:19 +0200
Hi,
Looks like twisting the implementation of the standard Spinbutton widget
is not quite easy to be achieved - maybe my alternative is quicker to
put to effective use.
I append code that I reduced from a gtk2 application I did a couple of
years ago, that implements a hex Spinbutton as a set of procedures. I am
leaving for 8 days of vacation tomorrow morning, did this very rapidly
without doing much testing. However, I realized some things that need
improving: use fixed format + size of entry box, parametrize the number
of digits (presently hard-wired to 4 digits - as needed in my old
application): this code is an example of a an approach that works, but
needs to be improved to become a library procedure.
Not included in the example, but easy to implement, a "get_value" and a
"set_value" procedure, and possibly a "step" parameter. I also stuck to
keeping this a set of procedures, rather than implementing a widget.
Juergen
============ demo code of a hex spin-button implementation ==========
============ for adequate display, set editor tabs to 4 ==========
#! /usr/bin/perl
use strict;
use warnings;
use diagnostics;
use Gtk2 '-init';
use Glib qw (TRUE FALSE );
use constant SPIN_HEIGHT => 16; # height of arrow pixmap (must
# correspond to
pixmap data)
use constant SPIN_MIDDLE => ( SPIN_HEIGHT / 2 );
use constant VERT_MARGIN => 3; # top and bottom margin of widget
use constant REPEAT_LATENCY => 700; # msec before first auto repeat
use constant REPEAT_INTERVAL => 30; # msec before following auto repeat
# Pixmap for arrow item of hex pseudo spinbox
# -------------------------------------------
my $arrow_xpm = Gtk2::Gdk::Pixbuf->new_from_xpm_data (
"11 16 3 1",
" c None",
"+ c Black",
"- c Gray80",
" -+- ",
" -+++- ",
" -++-++- ",
" -++- -++- ",
"-++- -++-",
"--- ---",
" ",
" ",
" ",
" ",
"--- ---",
"-++- -++-",
" -++- -++- ",
" -++-++- ",
" -+++- ",
" -+- " );
# Arrow-button event in pseudo-spinbox entry widget
# =================================================
# Argument #0 : entry widget (pseudo spinbutton)
# #1 : entry-item-position step: +1 or -1
# #2 : event ''
# #3 : threshold y-coordinate between up and down zone
sub SpinarrowHit {
my ( $p_box, $p_pos, $p_event, $p_middle ) = @_;
my ( $x_step, $time_out );
if ( ${$p_box}{'REPEAT'} ne '' ) {
# Spin arrow button released: cancel repeat timer
Glib::Source->remove ( ${$p_box}{'REPEAT'} );
${$p_box}{'REPEAT'} = '';
}
if ( ref ($p_event) =~ /Button/ ) {
# Spin arrow button pressed: step the value, set repeat timer
if ( index ($p_event->type, 'release' ) > 0 ) {
unless ( ${$p_box}{'REPEAT'} eq '' ) {
Glib::Source->remove ( ${$p_box}{'REPEAT'} );
${$p_box}{'REPEAT'} = '';
}
return;
}
my $pos_y = $p_event->y;
if ( $pos_y <= $p_middle - 1 ) {
$x_step = 1;
} elsif ( $pos_y > $p_middle + 1 ) {
$x_step = -1;
} else {
return;
}
$time_out = REPEAT_LATENCY;
} else {
# Repeat timer struck: step and re-launch the repeat timer
$x_step = $p_pos;
$time_out = REPEAT_INTERVAL;
}
my $x_value = $p_box->get_text ();
$x_value =~ s/\s*//;
unless ( $x_value =~ /^[0-9a-f]+$/i ) { return; }
$x_value= hex ( $x_value );
if ( ( $x_step == 1 ) && ( $x_value >= ${$p_box}{'MAX'} ) ) { return; }
if ( ( $x_step == -1 ) && ($x_value <= ${$p_box}{'MIN'} ) ) { return; }
${$p_box}{'VALUE'} = $x_value + $x_step;
$p_box->set_text ( sprintf ( "%04x", $x_value + $x_step ) );
${$p_box}{'REPEAT'} = Glib::Timeout->add ( $time_out,
sub {
SpinarrowHit ( $p_box, $x_step, '', $p_middle );
return FALSE;
} );
} # sub SpinarrowHit
# Check contents of the pseudo spinbox against non-hex characters
# ===============================================================
# Restore to last valid value in case of error
#
# Argument #0 : entry widget (pseudo spinbutton)
# #1 : entry-item-position step: +1 or -1
# #2 : event
sub SpinvalueCheck {
my ( $p_box, $p_pos, $p_event ) = @_;
my $new_value;
my $old_value = ${$p_box}{'VALUE'};
my $x_shown = $p_box->get_text ();
if ( $x_shown =~ /^[0-9a-f]+$/i ) {
$new_value = hex ( $x_shown );
${$p_box}{'VALUE'} = $new_value;
} else {
$new_value = $old_value;
$p_box->set_text ( sprintf ( "%04x", $old_value ) );
}
} # SpinvalueCheck
# Create a hex Spinbutton
# =======================
# Argument #0 : intial value
# #1 : lower limit
# #2 : upper limit
#
# Return: entry widget created (pseudo spinbutton)
#
# - program calls: numeric values are represented as perl values
# - spinbox display: values are represented as hex strings
# - contents of the entry widget are verified (only hex digits?) when
# focus is lost: in case of an error, revert to the last valid hex value.
#
# State variables attached as hash values:
# ${$widget}{VALUE} last accepted value
# ${$widget}{MIN} lowest value
# ${$widget}{MAX} highest accepted value
# ${$widget}{REPEAT} id of repeat timer
sub HexSpinButton {
my ( $p_value, $p_min, $p_max ) = @_;
my $w_temp = Gtk2::Entry->new_with_max_length (4);
$w_temp->set_editable ( TRUE );
$w_temp->set_size_request ( 70, -1 );
$w_temp->set_icon_from_pixbuf ( 'secondary', $arrow_xpm );
$w_temp->set_icon_activatable ( 'secondary', TRUE );
$w_temp->set_inner_border ( { 'left'=>4, 'right'=>0,
'top'=>VERT_MARGIN, 'bottom'=>VERT_MARGIN } );
$w_temp->signal_connect ( 'icon-press', \&SpinarrowHit, SPIN_MIDDLE );
$w_temp->signal_connect ( 'icon-release', \&SpinarrowHit, SPIN_MIDDLE );
$w_temp->signal_connect ( 'leave-notify-event', \&SpinvalueCheck );
$w_temp->set_text ( sprintf ( "%04x", $p_value ) );
${$w_temp}{'VALUE'} = sprintf ( $p_value );
${$w_temp}{'MIN'} = $p_min;
${$w_temp}{'MAX'} = $p_max;
${$w_temp}{'REPEAT'} = '';
return $w_temp;
} # sub HexSpinButton
# Main procedure (demo)
# =====================
my $f_main = Gtk2::Window->new( 'toplevel' );
my $f_outer = Gtk2::HBox->new ();
$f_outer->set_size_request ( 300, 200 );
$f_main->add ( $f_outer );
my $spin_button = HexSpinButton ( 0x13, 1, 0x100 );
$f_outer->pack_start ( $spin_button, TRUE, FALSE, 0 );
$f_main->show_all;
Gtk2->main;
exit ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]