PHP-GTK
Friday, September 19, 2014 
download | documentation | applications | faq | changelog | resources 


search for in the  


previousBasic Object Orientation
Summarynext

Last updated: Sun, 12 May 2013
view this page in English

We haven't used most of PHP5 powerful object oriented features so far. Let's make an application that opens a text file and displays its contents to you: a simple notepad-kind-of application. Please note that is a very very simple application meant for educational purposes and has no practical functionality! Here is the code, read it, and don't be intimidated by its size. A detailed explanation follows the code:

Example 8.2. A simple notepad

<?php
 
class Notepad extends GtkWindow
{
    protected $currentFile;
    protected $buffer;
    protected $status;
    protected $context;
    protected $lastid;
 
    function __construct($fileName = null)
    {
        parent::__construct();
                
        $mainBox  = new GtkVBox();
        $textBuff = new GtkTextBuffer();
        $textView = new GtkTextView($textBuff);
        $statusBar= new GtkStatusBar();
 
        $mainBox->pack_start($this->buildMenu(), false, false);
        $mainBox->pack_start($textView, true, true);
        $mainBox->pack_start($statusBar, false, false);
 
        $this->currentFile = $fileName;
        $this->buffer = $textBuff;
        $this->status = $statusBar;
 
        $this->connect_simple('destroy', array($this, 'quit'));
        $this->set_title('Simple Notepad');
        $this->maximize();
        $this->add($mainBox);
        $this->show_all();
 
        $this->loadFile();
    }
 
    function buildMenu()
    {
        $menuBar  = new GtkMenuBar();
        $fileMenu = new GtkMenu();
        $menuName = new GtkMenuItem('_File');
        
        $quit = new GtkImageMenuItem('gtk-quit');
        $quit->connect_simple('activate', array($this, 'quit'));
        $quit->connect_simple('enter_notify_event', 
                                array($this, 'updateStatus'), 1);
        $quit->connect_simple('leave_notify_event', 
                                array($this, 'updateStatus'), 0);
        
        $fileMenu->append($quit);
        $menuName->set_submenu($fileMenu);
        $menuBar->add($menuName);
 
        return $menuBar;
    }
   
    function loadFile()
    {
        if($this->currentFile != null) {
            $contents = file_get_contents($this->currentFile);
            $this->buffer->set_text($contents);
        }
    }
 
    function updateStatus($enter)
    {
        if($enter) {
            $id = $this->status->get_context_id("Message");
            $lastMsg = $this->status->push($id, "Quits the Application");
            $this->context = $id;
            $this->lastid = $lastMsg;
        } else {
            $this->status->remove($this->context, $this->lastid);
        }
    }
    
    function quit()
    {
        Gtk::main_quit();
    }
 
}
 
new Notepad('simple.phpw');
Gtk::main();
 
?>

The class structure is similar to what we have seen before, except the addition of some class properties and functions. Let's first have a look at the constructor. The constructor takes a single optional argument that defaults to null. That parameter is (path of) the file name that we wish to open. If you don't pass a parameter to the constructor, it will simply open nothing.

OK, so we first construct the parent (a GtkWindow) and then create some widgets that we will use. A GtkVBox for our layout, a GtkTextBuffer and a GtkTextView to display the contents of the file and a GtkStatusBar to display some messages. We setup the layout and add the respective widgets to the VBox.

Next we set the class properties:

$this->currentFile = $fileName;
$this->buffer = $textBuff;
$this->status = $statusBar;
These three lines set the values for the class properties. Class properties are an essential part of all object-oriented PHP-GTK 2 applications. They are useful because you may need to access a particular widget in a function that it was not created in. When we create a widget, the object's scope is only within the function it was created in. For example, we created the status bar in the constructor of our class, but we obviously need to access it elsewhere (when we need to put some messages on it). But since the variable $statusBar can be accessed only within the constructor, we assign a class property (called status) to it. Now we can access the status bar in any function within the class by using $this->status.

Simply extend this concept to other widgets too. Basically, you need to assign class properties to widgets that you think will need the entire class as its scope. Actually, class properties can also be used efficiently to store any data that you may need across the entire class. One example of this in our applications is the currentFile property. This will simply store the path of the current file opened, or null if none is. We can then find out the name of the current file opened in any function of the class. Class properties have other uses too, one such use I can think of is a flag. For our notepad application, you may want to add a class property called saved which will have Boolean values to indicate whether the current file has been saved to disk or not.

Note that all the class properties have been defined as protected. This is simply a good object oriented practice. We don't want them to be public but we also want any classes that extends ours to be able to access them.

And finally, we set the title of the window, maximize it, add the layout and display all the widgets. And then we call the loadFile() function to display the contents of our file in the text buffer that we had created.

Note how we had called this function from the constructor:

$mainBox->pack_start($this->buildMenu(), false, false);
We do that because we want to want to split our class into as many modules as possible. Instead of building our entire layout in the constructor itself, it is better to split the layout into major parts and dedicate a function for each part. Here we have a function to build the menu bar, but not for the text view or status bar because they take only 2 lines each to construct!

In this function, we just create our menu bar, add a simple file menu with a single "Quit" button to it. Let's have a look at these lines:

$quit->connect_simple('activate', array($this, 'quit'));
$quit->connect_simple('enter_notify_event', array($this, 'updateStatus'), 1);
$quit->connect_simple('leave_notify_event', array($this, 'updateStatus'), 0);
Here we connect the activate, enter-notify-event and leave-notify-event to their respective handlers. Look at the second parameter to the connect_simple() functions. It is an array with two elements. The first element is the special $this variable and the second element is a string. If you had read the
Hello World tutorial, you would have come across a line like this:
$wnd->connect_simple('destroy', array('gtk', 'main_quit'));
Compare the usages and it should dawn on you that whenever you want to connect a signal to callback function which is in a class, you must specify the callback as an array, the first element of which points to the class, and the second element of which is the name of the callback. Hence, we connect the various events of our quit button to this classes' quit() and updateStatus() functions.

Sometimes, it is possible to pass parameters to functions in order to use those objects in the function. As a rule of thumb, if you have more than one function that uses a particular object, it is better to dedicate a class property to it; but if there is only a single function that requires the object, it is better to pass the object as a parameter instead. A common occurrence of this situation is while connecting signals to callbacks. Have a look at the tutorial on signals and callbacks for more on this and how to pass custom parameters to the callbacks.

Getting back to the function, we return the top-most widget in our menu: the menu bar, after adding the sub-menu to it. The constructor then receives this object and adds it to the main VBox.


User Contributed Notes
tutorials.objectorientation.advanced.php
add a note about notes
There are no user contributed notes for this page.


previousBasic Object Orientation
Summarynext

Last updated: Sun, 12 May 2013
view this page in English


credits 

PHP  Copyright © 2001-2014 The PHP Group
 All rights reserved.
Last updated: Sun May 12 20:51:01 2013 CEST