IPEntry
is a widget that allows the user to enter an IPv4 address.
It performs some checks to see if user input is valid and
implements the get_text() and
set_text() methods.
<?php
/**
* IPv4 Entry widget
*
* IPEntry performs some checks to see if userinput is valid and implements the
* get_text() and set_text() methods found in regular GtkEntry widgets for
* compatibility and ease of use.
*
* Small warning note: Needs to be fitted within a GtkAlignment because it will
* take up all available space otherwise.
*
* @author Robert van der Linde <robert@linde002.nl>
* @version 1.0
*/
class IPEntry extends GtkFrame
{
/**
* Contains the four GtkEntry fields.
*
* @var array
*/
protected $aEntries = array();
/**
* The GtkEntry currently selected
*
* @var int
*/
protected $iCurrentEntry = 0;
/**
* Creates a IPEntry widget
*
*/
public function __construct()
{
parent::__construct();
/**
* The container for all the GtkEntries
*/
$oHBox = new GtkHBox();
/**
* Create four GtkEntry fields
*/
for ($x=0; $x<4; $x++)
{
$this->aEntries[$x] = new GtkEntry();
/**
* Align the text in the middle of the GtkEntry. Looks pretty
*/
$this->aEntries[$x]->set_property ('xalign', 0.5);
$this->aEntries[$x]->set_property ('has-frame', 0);
$this->aEntries[$x]->set_size_request (30, -1);
/**
* Default to 0
*/
$this->aEntries[$x]->set_text('0');
/**
* Connect the callback signals used to perform input checking
*/
$this->aEntries[$x]->connect('key-press-event', array($this, 'onButtonDown'), $x);
$this->aEntries[$x]->connect('key-release-event', array($this, 'onButtonUp'), $x);
$oHBox->pack_start($this->aEntries[$x], 0);
/**
* If this is the last entry field don't add the dot.
*/
if($x != 3)
$oHBox->pack_start(new GtkLabel('.'), 0);
}
/**
* Pack it all in a pretty eventbox so we can set the general background color.
*/
$oEventBox = new GtkEventBox();
$oEventBox->add($oHBox);
$oEventBox->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse("#ffffff"));
$this->add($oEventBox);
$this->set_shadow_type(Gtk::SHADOW_ETCHED_OUT);
}
/**
* Called when a user starts inputting a character. If that character is a dot
* we jump to the next entry field and suppress the dot.
*
* @param GtkEntry $oEntry
* @param GdkEvent $oEvent
* @param int $iEntryid
* @return boolean
*/
public function onButtonDown(GtkEntry $oEntry, GdkEvent $oEvent, $iEntryid)
{
if(chr($oEvent->keyval) == '.')
{
$sTxt = $oEntry->get_text();
if($iEntryid == 3)
$this->aEntries[0]->grab_focus();
else
$this->aEntries[$iEntryid+1]->grab_focus();
return true;
}
else
return false;
}
/**
* Called when a user finishes inputting a character. If the character is
* the third digit or by inputting the character makes the value higher then 25
* jump to the next inputfield.
*
* @since 1.0
* If this inputfield is selected by way of using TAB or dot we do not check the
* value of the input fields. This is a workaround to stop the widget from entering
* a possible infiniteloop when all input fields are > 25
*
* @param GtkEntry $oEntry
* @param GdkEvent $oEvent
* @param int $iEntryid
*/
public function onButtonUp(GtkEntry $oEntry, GdkEvent $oEvent, $iEntryid)
{
if($oEvent->keyval != Gdk::KEY_Tab && chr($oEvent->keyval) != '.')
{
if(strlen(trim($oEntry->get_text())) == 3 || trim($oEntry->get_text()) > 25)
{
if($iEntryid == 3)
$this->aEntries[0]->grab_focus();
else
$this->aEntries[$iEntryid+1]->grab_focus();
}
/**
* If the inputfield has a value higher then 255 reset it to 255
*/
if(trim($oEntry->get_text()) > 255)
$oEntry->set_text('255');
}
}
/**
* Implementation of the GtkEntry::set_text() function for usability.
* Checks if the string is a valid ip address (does it's best to create
* one if it received an invalid string)
*
* When it fails to do so defaults to 0.0.0.0
*
* @param string $sIP
*/
public function set_text($sIP)
{
$sCleanIP = long2ip(ip2long($sIP));
$aIPSections = explode('.', $sCleanIP);
for($x=0; $x<4; $x++)
$this->aEntries[$x]->set_text($aIPSections[$x]);
}
/**
* Implementation of the GtkEntry::get_text() function for usability.
* Returns a concatenation of the GtkEntry fields and dots.
*
* @return string
*/
public function get_text()
{
$sIP = '';
for($x=0; $x<4; $x++)
{
$sIP .= trim($this->aEntries[$x]->get_text());
if($x != 3)
$sIP .= ".";
}
return $sIP;
}
}
?>
Update
Fixed the erroneous skipping behaviour that occured when skipping through fields that already had input in them. Should work fine now.
Comments
an other version
for your information, I have an other version with more subclassing at this location : http://php.classes.free.fr/php/gtk/IpEntry/IpEntry-php.txt
Possible addition to the application?
Maybe adding a classfull subnet sugestion based on the address used. and the possible hosts available in that
subnet might be a nice addition.
Logic.
Class A 0-126 ((+128) - 1 - Reserved 127 Non Inet Routable 10) 255.0.0.0 2^24 = 16777216 - 2 Hosts
Class B 128 - 191 ((+64) - 1 - Non Inet Routable 172.10) 255.255.0.0 2^16 = 65536 - 2 Hosts
Class C 192 - 223 ((+32) - 1 - Non Inet Routable 192.168) 255.255.255.0 2^8 = 256 - 2 Hosts
Class D (Experimental) etc