set_ip('10.0.0.155'); * $ip_entry->get_ip(); */ error_reporting(E_ALL); class Field extends GtkEntry{ protected $size; protected $value; protected $accept_chars; public function __construct($value, $size, $accept_chars = '.'){ parent::__construct($value, $size); $this->set_property ('has-frame', false); $this->set_width_chars(3); $this->set_alignment(0.5); $this->accept_chars = $accept_chars; # regular expression $this->connect('key-press-event', array($this, 'on_key_pressed')); // note 1 } public function on_key_pressed($widget, $event){ # print_r($event); # this is a special key, not a char key if($event->string == '') return false; if(preg_match('/'.$this->accept_chars.'/', $event->string)) return false; # accept event and propagate event else{ $this->alarm(); return true; # don't propagate event ; } } protected function alarm(){ Gdk::beep(); } } class IntegerField extends Field{ protected $min_value; protected $max_value; public function __construct($value, $size, $accept_chars = '\d', $min=0, $max=255){ parent::__construct($value, $size, $accept_chars ); $this->min_value = $min; $this->max_value = $max; } public function on_key_pressed($widget, $event){ # wrong chars - don't propagate event if(parent::on_key_pressed($widget, $event)) return true; # this is a special key, not a char key if($event->string == '') return false; # when focus change, text get selected ; we need to clear it before allowing event propagation if($this->get_selection_bounds() != false){ $this->set_text(''); return false; } $value = $this->get_text() . $event->string; if(intval($value) > $this->max_value){ $this->alarm(); return true; } /** very difficult to check as user is typing if(intval($value) < $this->min_value){ $this->alarm(); return true; } */ return false; } } class FixedField extends GtkLabel{ public function __construct($value, $size){ parent::__construct($value); } } class IpEntry extends GtkFrame{ protected $hbox; protected $event_box; protected $entries; protected $active_entry; public function __construct(){ parent::__construct(); $this->entries = array(); $this->active_entry = 0; $this->setupGUI(); } protected function setupGUI(){ $this->hbox = new GtkHbox(); $this->event_box = new GtkEventBox(); $accept_chars = '[\d\.]'; for($i = 0 ; $i<4 ; $i++){ $this->entries[$i] = $e = new IntegerField('', 3, $accept_chars); $e->connect_after('insert-text', array(&$this, 'entry_on_char_insert')); $e->connect('key-press-event', array($this, 'entry_on_key_pressed')); $e->connect('button-press-event', array($this, 'entry_on_button_pressed')); # to track focus for rigth entry $e->set_data('id', $i); $this->hbox->pack_start($e, false, false); if($i<3){ $f = new FixedField('.', 1); $this->hbox->pack_start($f, false, false); } } $this->add($this->event_box); $this->event_box->add($this->hbox); $this->event_box->connect('key-press-event', array($this, 'on_key_pressed')); $this->set_shadow_type(Gtk::SHADOW_IN); $this->event_box->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('white')); } public function entry_on_char_insert($widget, $str, $len, $pointer){ # goto next fiel if use type '.' ; and remove '.' from entry content if($str == '.'){ $widget->set_text(trim($widget->get_text(), '.')); $this->field_focus_next(); } if(strlen($widget->get_text() == 3)) $this->field_focus_next(); } public function entry_on_button_pressed($widget, $event){ # set active entry widget based on 'id' $this->active_entry = $widget->get_data('id'); } public function entry_on_key_pressed($widget, $event){ switch($event->keyval){ case Gdk::KEY_BackSpace: if(strlen($widget->get_text() <=2 )){ $widget->set_text(''); $this->field_focus_prev($unselect = true); return true; # don't propagate event any more } break; case Gdk::KEY_Left: if($widget->get_position() == 0){ $this->field_focus_prev($unselect = true); return true; # don't propagate event any more } break; case Gdk::KEY_Right: $len = strlen($widget->get_text()); $pos = $widget->get_position(); if($widget->get_position() == $len){ $this->field_focus_next($unselect = true); return true; # don't propagate event any more } break; } return false; # accept event and propagate event } public function on_key_pressed($widget, $event){ switch($event->keyval){ case Gdk::KEY_Tab: case Gdk::KEY_Return: $this->field_focus_next(); break; case Gdk::KEY_ISO_Left_Tab: $this->field_focus_prev(); break; } return true; } protected function field_focus_next($unselect=false){ $this->active_entry++; if($this->active_entry >= count($this->entries)) $this->active_entry = 0; $this->field_goto($this->active_entry); if($unselect) $this->entries[$this->active_entry]->set_position(0); } protected function field_focus_prev($unselect=false){ $this->active_entry--; if($this->active_entry < 0) $this->active_entry = count($this->entries) -1; $this->field_goto($this->active_entry); if($unselect) $this->entries[$this->active_entry]->set_position(3); } protected function field_goto($index){ if(isset($this->entries[$index])){ $this->active_entry = $index; $this->entries[$index]->grab_focus(); return true; } return false; } protected function focus_reset(){ foreach($this->entries as $e){ $e->set_position(0); } $this->field_goto(0); } public function get_ip(){ $values = array(); foreach($this->entries as $e){ $values[]= $e->get_text(); } return join('.', $values); } public function set_ip($ip){ $values = split('\.', $ip); if(count($values) != 4) throw new Exception("ip ($ip) is not correct"); foreach($values as $v){ if(!ctype_digit($v)) throw new Exception("ip ($ip) is not correct - some part is not a number ($v)"); } foreach($this->entries as $key=>$entry){ $entry->set_text($values[$key]); } $this->focus_reset(); } } // Create a new window. $window = new GtkWindow(); // Properly handle closing of the window. $window->connect_simple('destroy', array('Gtk', 'main_quit')); $window->set_title('IpEntry'); $vbox = new GtkVbox(); $window->add($vbox); $vbox->pack_start(new GtkLabel('IP Adresse :'), false, false); $vbox->pack_start($ip_entry = new IpEntry(), false, false); # $ip_entry->set_ip('10.0.0.155'); $vbox->pack_start($button = new GtkButton('OK'), false, false); $button->connect('clicked', 'get_ip', $ip_entry); # $window->set_size_request(400, 300); $window->set_position(Gtk::WIN_POS_CENTER); $window->show_all(); Gtk::main(); function get_ip($button, $ip_entry){ echo "ip = " . $ip_entry->get_ip() . "\n"; } ?>