Layout management in PHP GTK

In this chapter we will show how to lay out our widgets in windows or dialogs.

When we design the GUI of our application, we decide what widgets we will use and how we will organise those widgets in the application. To organise our widgets, we use specialised non visible widgets called layout containers. In this chapter, we will mention GtkAlignment, GtkFixed, GtkVBox and GtkTable.

GtkFixed

The GtkFixed container places child widgets at fixed positions and with fixed sizes. This container performs no automatic layout management. In most applications, we do not use this container. There are some specialised areas, where we use it. For example games, specialised applications that work with diagrams, resizable components that can be moved (like a chart in a spreadsheet application), small educational examples.

<?php

/* 
ZetCode PHP GTK tutorial

In this program, we lay out widgets
using absolute positioning.

author: Jan Bodnar
website: www.zetcode.com
last modified: September 2011
*/
 
class Example extends GtkWindow { 
     

    public function __construct() { 

        parent::__construct(); 
         
        $this->init_ui();

    } 

    public function init_ui() {

        $this->set_title('Fixed');         
        $this->connect_simple('destroy', array('gtk', 'main_quit')); 

        $this->modify_bg(Gtk::STATE_NORMAL, new GdkColor(6400, 6400, 6440));

        $bardejov = GtkImage::new_from_file("bardejov.jpg");
        $rotunda = GtkImage::new_from_file("rotunda.jpg");
        $mincol = GtkImage::new_from_file("mincol.jpg");
        
        $fixed = new GtkFixed();
        $fixed->put($bardejov, 20, 20);
        $fixed->put($rotunda, 40, 160);
        $fixed->put($mincol, 170, 50);

        $this->add($fixed);        


        $this->set_default_size(300, 280); 
        $this->set_position(GTK::WIN_POS_CENTER);
        $this->show_all();         
 
    }
} 
     
new Example(); 
Gtk::main();
 
?>

In our example, we show three small images on the window. We explicitly specify the x, y coordinates, where we place these images.

$this->modify_bg(Gtk::STATE_NORMAL, new GdkColor(6400, 6400, 6440));

For better visual experience, we change the background color to dark gray.

$bardejov = GtkImage::new_from_file("bardejov.jpg");

The GtkImage is a widget that is used to display images. The picture is loaded from the file on the disk.

$fixed = new GtkFixed();

We create the GtkFixed container.

$fixed->put($bardejov, 20, 20);

We place the first image at x=20, y=20 coordinates.

w.add(fixed);

Finally, we add the GtkFixed container to the Window.

Fixed
Figure: Fixed

Buttons

In this code example, we will use a vertical box, a horizontal box, and an alignment widget. A horizontal box arranges widgets in a single row. Similarly, a vertical box places its widgets in one column. The Alignment container controls the alignment and the size of its child widget.

<?php
 
/* 
ZetCode PHP GTK tutorial

In this program, we position two buttons
in the bottom right corner of the window.
We use horizontal and vertical boxes.

author: Jan Bodnar
website: www.zetcode.com
last modified: August 2011
*/

class Example extends GtkWindow { 
     

    public function __construct() { 

        parent::__construct(); 
         
        $this->init_ui();

    } 

    public function init_ui() {

        $this->set_title('Buttons');         
        $this->connect_simple('destroy', array('gtk', 'main_quit')); 
        $this->set_border_width(3);

        $vbox = new GtkVBox(false, 5);
        $hbox = new GtkHBox(true, 3);

        $frame = new GtkFrame();
        $vbox->pack_start($frame, true, true, 0);

        $okButton = new GtkButton("OK");
        $okButton->set_size_request(70, 30);
        $closeButton = new GtkButton("Close");

        $hbox->add($okButton);
        $hbox->add($closeButton);
        
        $halign = new GtkAlignment(1, 0, 0, 0);
        $halign->add($hbox);
        $vbox->pack_start($halign, false, false, 3);

        $this->add($vbox);        

        $this->set_default_size(260, 150); 
        $this->set_position(GTK::WIN_POS_CENTER);
        $this->show_all();          
    }
} 
     
new Example(); 
Gtk::main();
 
?>

In the code example, we place two buttons into the right bottom corner of the window. To accomplish this, we use one horizontal box and one vertical box and one alignment container.

$vbox = new GtkVBox(false, 5);

A vertical box container is created. We set the homogeneous member to false. This means that widgets put into the vertical box will hot have the same size. The vertical spacing between widgets is set to 5 pixels.

$frame = new GtkFrame();

Here we create a GtkFrame widget. The purpose of this widget is to take up space above the two buttons.

$vbox->pack_start($frame, true, true, 0);

Here we place the frame widget into the vertical box. The first parameter of the method is the widget, which is being placed into the box. The following three parameters are expand, fill and padding. The expand parameter is set to true, which means that free space will be allocated around the widget. When the fill parameter is set to true, the widget actually takes up all the free space around it. There is no padding around the child widget.

$hbox = new GtkHBox(true, 3);  

This code line creates a horizontal box. All widgets inside the box will have the same size. There will be 3px space between the widgets horizontally.

$okButton = new GtkButton("OK");
$okButton->set_size_request(70, 30);
$closeButton = new GtkButton("Close");

$hbox->add($okButton);
$hbox->add($closeButton);

We create two buttons and put them inside the horizontal box.

$halign = new GtkAlignment(1, 0, 0, 0);
$halign->add($hbox);
$vbox->pack_start($halign, false, false, 3);

This will create an alignment container that will place its child widget to the right. The xalign member set to 1.0 will put all free space to the left of the horizontal box. This will push the two buttons to the right. We add the horizontal box into the alignment container and pack the alignment container into the vertical box. We must keep in mind that the alignment container takes only one child widget. That's why we must use the horizontal box.

Buttons
Figure: Buttons

Calculator skeleton

The GtkTable widget arranges widgets in rows and columns.

<?php
 
/* 
ZetCode PHP GTK tutorial

In this program we create a skeleton of
a calculator. We use the GtkTable widget.

author: Jan Bodnar
website: www.zetcode.com
last modified: August 2011
*/

class Example extends GtkWindow { 
     

    public function __construct() { 

        parent::__construct(); 
         
        $this->init_ui();

    } 

    public function init_ui() {

        $this->set_title('Calculator');         
        $this->connect_simple('destroy', array('gtk', 'main_quit')); 

        $vbox = new GtkVBox(false, 2);

        $mb = new GtkMenubar();
        $filemenu = new GtkMenu();
        $filemi = new GtkMenuItem("File");
        $filemi->set_submenu($filemenu);
        $mb->append($filemi);

        $vbox->pack_start($mb, false, false, 0);

        $table = new GtkTable(5, 4, true);

        $table->attach_defaults(new GtkButton("Cls"), 0, 1, 0, 1);
        $table->attach_defaults(new GtkButton("Bck"), 1, 2, 0, 1);
        $table->attach_defaults(new GtkLabel(), 2, 3, 0, 1);
        $table->attach_defaults(new GtkButton("Close"), 3, 4, 0, 1);

        $table->attach_defaults(new GtkButton("7"), 0, 1, 1, 2);
        $table->attach_defaults(new GtkButton("8"), 1, 2, 1, 2);
        $table->attach_defaults(new GtkButton("9"), 2, 3, 1, 2);
        $table->attach_defaults(new GtkButton("/"), 3, 4, 1, 2);

        $table->attach_defaults(new GtkButton("4"), 0, 1, 2, 3);
        $table->attach_defaults(new GtkButton("5"), 1, 2, 2, 3);
        $table->attach_defaults(new GtkButton("6"), 2, 3, 2, 3);
        $table->attach_defaults(new GtkButton("*"), 3, 4, 2, 3);

        $table->attach_defaults(new GtkButton("1"), 0, 1, 3, 4);
        $table->attach_defaults(new GtkButton("2"), 1, 2, 3, 4);
        $table->attach_defaults(new GtkButton("3"), 2, 3, 3, 4);
        $table->attach_defaults(new GtkButton("-"), 3, 4, 3, 4);

        $table->attach_defaults(new GtkButton("0"), 0, 1, 4, 5);
        $table->attach_defaults(new GtkButton("."), 1, 2, 4, 5);
        $table->attach_defaults(new GtkButton("="), 2, 3, 4, 5);
        $table->attach_defaults(new GtkButton("+"), 3, 4, 4, 5);

        $vbox->pack_start(new GtkEntry(), false, false, 0);
        $vbox->pack_end($table, true, true, 0);

        $this->add($vbox);        

        $this->set_default_size(300, 250); 
        $this->set_position(GTK::WIN_POS_CENTER);
        $this->show_all();         
 
    }
} 
     
new Example(); 
Gtk::main();
 
?>

We use the GtkTable widget to create a calculator skeleton.

$table = new GtkTable(5, 4, true);

We create a table widget with 5 rows and 4 columns. The third parameter is the homogenous parameter. If set to true, all the widgets in the table are of the same size. The size of all widgets is equal to the largest widget in the table container.

$table->attach_defaults(new GtkButton("Cls"), 0, 1, 0, 1);

We attach a button to the table container. To the top-left cell of the table. The first two parameters are the left and right sides of the cell, the last two parameters are the top and left sides of the cell.

$vbox->pack_end($table, true, true, 0);

We pack the table widget into the vertical box.

Calculator skeleton
Figure: Calculator skeleton

Windows

Next we will create a more advanced example. We show a window, that can be found in the JDeveloper IDE.

<?php
 
/* 
ZetCode PHP GTK tutorial

This is a more complicated layout example.
We use GtkAlignment and GtkTable widgets. 

author: Jan Bodnar
website: www.zetcode.com
last modified: August 2011
*/

class Example extends GtkWindow { 
     

    public function __construct() { 

        parent::__construct(); 
         
        $this->init_ui();
    } 

    public function init_ui() {

        $this->set_title('Windows');         
        $this->connect_simple('destroy', array('gtk', 'main_quit')); 

        $this->set_border_width(15);

        $table = new GtkTable(8, 4, false);
        $table->set_col_spacings(3);
        
        $title = new GtkLabel("Windows");
       
        $halign = new GtkAlignment(0, 0, 0, 0);
        $halign->add($title);        
        $table->attach($halign, 0, 1, 0, 1, GTK::FILL, 
            GTK::FILL, 0, 0);
        
        $frame = new GtkFrame();
        $table->attach($frame, 0, 2, 1, 3, GTK::FILL | Gtk::EXPAND,
            GTK::FILL | GTK::EXPAND, 1, 1);

        $activate = new GtkButton("Activate");
        $activate->set_size_request(50, 30);
        $table->attach($activate, 3, 4, 1, 2, GTK::FILL,
            GTK::SHRINK, 1, 1);

        $valign = new GtkAlignment(0, 0, 0, 0);
        $close = new GtkButton("Close");
        $close->set_size_request(70, 30);
        $valign->add($close);
        $table->set_row_spacing(1, 3);
        $table->attach($valign, 3, 4, 2, 3, Gtk::FILL,
            Gtk::FILL | Gtk::EXPAND, 1, 1);

        $halign2 = new GtkAlignment(0, 1, 0, 0);
        $help = new GtkButton("Help");
        $help->set_size_request(70, 30);
        $halign2->add($help);
        $table->set_row_spacing(3, 6);
        $table->attach($halign2, 0, 1, 4, 5, Gtk::FILL,
            Gtk::FILL, 0, 0);
        
        $ok = new GtkButton("OK");
        $ok->set_size_request(70, 30);
        $table->attach($ok, 3, 4, 4, 5, Gtk::FILL,
            Gtk::FILL, 0, 0);

        $this->add($table);        

        $this->set_default_size(300, 250); 
        $this->set_position(GTK::WIN_POS_CENTER);
        $this->show_all();         
    }
} 
     
new Example(); 
Gtk::main();
 
?>

The code example shows, how we can create a similar window in PHP GTK.

$table = new GtkTable(8, 4, false);
$table->set_col_spacings(3);

The example is based on the GtkTable container. There will be 3px space between columns.

$title = new GtkLabel("Windows");

$halign = new GtkAlignment(0, 0, 0, 0);
$halign->add($title);        
$table->attach($halign, 0, 1, 0, 1, GTK::FILL, 
    GTK::FILL, 0, 0);

This code creates a label that is aligned to the left. The label is placed in the first row of the first column of the Table container.

$frame = new GtkFrame();
$table->attach($frame, 0, 2, 1, 3, GTK::FILL | Gtk::EXPAND,
    GTK::FILL | GTK::EXPAND, 1, 1);

The frame widget spans two rows and two columns. It will consume all free space around it. Thus, taking the bulk of the area of the window.

$valign = new GtkAlignment(0, 0, 0, 0);
$close = new GtkButton("Close");
$close->set_size_request(70, 30);
$valign->add($close);
$table->set_row_spacing(1, 3);
$table->attach($valign, 3, 4, 2, 3, Gtk::FILL,
    Gtk::FILL | Gtk::EXPAND, 1, 1);

We put the close button next to the frame widget into the fourth column. (we count from zero) We add the button into the alignment widget, so that we can align it to the top.

$halign2 = new GtkAlignment(0, 1, 0, 0);
$help = new GtkButton("Help");
$help->set_size_request(70, 30);
$halign2->add($help);
$table->set_row_spacing(3, 6);
$table->attach($halign2, 0, 1, 4, 5, Gtk::FILL,
    Gtk::FILL, 0, 0);

The help button is placed into the alignment widget, so that it can be left aligned in its table cell. It is placed at the first column, fifth row.

$ok = new GtkButton("OK");
$ok->set_size_request(70, 30);
$table->attach($ok, 3, 4, 4, 5, Gtk::FILL,
    Gtk::FILL, 0, 0);

Finally the ok button. It is placed at the fourth column and fifth row.

Windows
Figure: Windows

In this part of the PHP GTK tutorial, we mentioned layout management of widgets.