GtkEntry : IPv4 Entry made simple with IPEntry

screenshot for IPEntry widgetIPEntry 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

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.