Demophone

From JGlade

Under construction

Contents

Introduction

Demophone is a fictional application, with relativelly simple complexity, to aid the evaluation of GUI builders and toolkits. This simmulates an Internet phone, but don't expect to place a call yet :-)

These are the screenshots of Demophone running on different platforms and toolkits (GTK, Windows and Motif). The application is the same and obtained from a single Glade UI design.

Demophone GTK Demophone SWT
Demophone Motif Demophone Win32

State diagram

Image:Demophone-state_diag.png

Building the GUI

This screenshot shows the GUI building process (almost finished) in

Glade.
Glade
Enlarge
Glade

You can see

  • the Glade main window, with the demophone project opened
  • the Glade palette
  • the Properties window, showing the main window's properties
  • the Tree view, showing the hierarchy of GTK widgets conforming

the demophone interface

  • the demophone main window

Creating the layout

This is the list of widgets that you have to create in order to obtain the desired interface

  • main window
    • vertical box (size 5)
      • textview
      • label
      • hbox (size 2)
        • button Yes
        • button No
      • table (size 3x4)
        • button 1
        • button 2
        • ...
        • button #
      • image

Step by step

Launch Glade UI designer by clicking on the menu entry or from the shell with

$ glade-2

Glade project

Project options
Enlarge
Project options

Create a new project using Net GTK+ Project. Go to Project->Options... and set project name and folder.

Main window

Select Window in the GTK+ Basic palette, to create the main window. Then, set Name and Title to demophone in properties.

Vertical box

Vertical box
Enlarge
Vertical box

Layouts in Glade are managed through horizontal and vertical boxes and tables. Select Vertical Box in the palette and set the number of rows to 4.

Text view

Select Textview from the palette and place it in the first row of the previously created Vertical Box. In properties set Name to textviewLCD, Editable to No and Cursor visible to No. By default, the textview is placed inside a scrolledwindow, you can see it in the Widget Tree, accessible through View->Show Widget Tree. Since we don't want scroll bars in our widget, we have to disable them in the scrolledwindow properties. Set H Scroll and V Scroll to Never.

Label

Select Label from the palette and place it in the second row of the Vertical Box. Set Name to labelStatus.

Horizontal Box

We now need an Horizontal Box to put the two action buttons. Select Horizontal Box and place it in the third row of the Vertical Box. Set the Number of columns to 2.

Button Yes

Select Button and place it in the left column of the Horizontal Box. Set Name to buttonYes, and Label to Yes. And set Expand and Fill to Yes in the packing tab.

Button No

Action buttons
Enlarge
Action buttons

Select Button and place it in the right column of the Horizontal Box. Set Name to buttonNo, and Label to No. And set Expand and Fill to Yes in the packing tab.

Table

Number buttons
Enlarge
Number buttons

Select Table and place it in the fourth row of the Vertical Box. Set Number of rows to 4 and Number of columns to 3.

Buttons

Select Button and fill every table cell with a button. Set Name and Label for every button indicating the button number. For example, name the first button button1 with label 1.

For the special case of * and # buttons, name them buttonStar and buttonNumeral respectively.

Image

Image
Enlarge
Image

Let's make some room to add an image at the bottom. Select vbox1 in Widget Tree, and increase the Size from 4 to 5.

Select Image from the palette and add it in the new row. In properties, set Icon to demophone.png.

Finishing touch

You can add borders and spacing to some widgets to improve visibility.

Defining the signals

Signals are the way to connect some event in the widget with functionality inside your code.

This signals have to be defined for the corresponding widgets

  • destroy for the main window (in order to exit the application when it is closed)
  • clicked on every number, '*' or '#' button, to provide the corresponding actions using handler on_button_clicked.
  • clicked on 'Yes' button, using handler on_action_button_clicked.
  • clicked on 'No' button using on_action_button_clicked.

To do this, select the corresponding widget (i.e: buttonYes) from Widget Tree, go to the Signals tab in properties and then select the desired signal or event (clicked in this case) in Signal, modify the proposed Handler name into one of the handlers defined in the previous list and press the Add button.

The signal is now connected with the method handler you defined.

Glade definition file

Saving the project you will obtain the Glade XML definition file Demophone.glade. This file is defined in http://glade.gnome.org/glade-2.0.dtd.

Pygtk example

One of the most common approaches is to use Pygtk and its libglade bindings. This can be used as a test.

View source code

JGlade example

This example demonstrates the use of JGlade to build the application.

Download software components

Downlod latest JGlade distribution jar, JGlade.jar, from http://sourceforge.net/project/showfiles.php?group_id=153625.

Download latest Demophone distribbution jar, Demophone.jar, from http://sourceforge.net/project/showfiles.php?group_id=153625.

You may also need to download the latest SWT version for you platform from http://eclipse.org/swt.

Extract resources

In the Demophone directory

jar -xvf Demophone.jar resources

Extract runner

In the Demophone directory and depending on your platform

jar -xvf Demophone.jar demophone.sh

or

jar -xvf Demophone.jar demophone.bat

Review settings

Some values can be configured to suit your environment. Check the runner script and edit it if necessary. These are the default settings for Linux and Unix.

#----------------------------------------------------------------------
# Configurable
#
JAVA_HOME=/opt/java/jdk1.5.0_05
SWTLIBDIR=/opt/java/swt-3.1.1-\$TK-linux-x86/
SWTJAR=$SWTLIBDIR/swt.jar
DEMOPHONELIBDIR=.
DEMOPHONEJAR=$DEMOPHONELIBDIR/Demophone.jar
JGLADELIBDIR=../JGlade
JGLADEJAR=$JGLADELIBDIR/JGlade.jar
#----------------------------------------------------------------------

Run demophone

Enlarge

Run the corresponding runner for your platform, for example in Linux and Unix

demophone.sh

and you will see something like this.

You can also specify a toolkit option, for exaample to use Motif

demophone.sh --motif

and Demophone will use SWT Motif.

Analyzing Demophone

Image:Demophone-class-diagram.png

package demophone;

import jglade.JGlade;
import jglade.JGladeConstructionExeption;
import jglade.toolkit.swt.SwtToolkit;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

public class Demophone extends JGlade {
	
	/**
	 * Demophone texview display
	 */
	private Text textviewLCD;

	/**
	 * Demophone status label
	 */
	private Label labelStatus;
	
	
	/**
	 * Demophone constructor, uses the XML file produced by Glade UI builder to build
	 * the interface.
	 * 
	 * @author diego
	 * @version 0.1
	 * 
	 * @throws JGladeConstructionExeption 
	 */
	public Demophone() throws JGladeConstructionExeption {
		super("resources/demophone.xml");
		
		final Color lcd = new Color(SwtToolkit.getDisplay(), 0xd5, 0xdb, 0xc5);
		
		textviewLCD = (Text)getWidget("textviewLCD");
		if ( textviewLCD != null ) {
			//textviewLCD.append("\n\n\n");
			textviewLCD.setBackground(lcd);
		}
		
		labelStatus = (Label)getWidget("labelStatus");
		if ( labelStatus != null ) {
			labelStatus.setBackground(lcd);
		}
		
		// initialize
		updateLCD("");
		updateStatus("");
		
		// event loop
		eventLoop();
	}

	/**
	 * Appends the digit n to the information displayed.
	 * 
	 * @param n the digit to display
	 */
	private void number(String n) {
		updateStatus("");
		textviewLCD.append(n);
	}
	
	/**
	 * Peroforms the requested action.
	 * 
	 * @param a the action to perform
	 */
	private void action(String a) {
		String text = "";
		
		if ( a.equals("Yes") ) {
			if ( textviewLCD.getText().equals("") ) {
				text = "No number";
			}
			else {
				text = "Calling...";
			}
		}
		else if ( a.equals("No") ) {
			updateLCD("");
		}
		
		updateStatus(text);
	}
	
	private void updateLCD(String text) {
		textviewLCD.setText(text);
	}
	
	private void updateStatus(String text) {
		labelStatus.setText(text);
	}
	/**
	 * This is a JGlade signal handler
	 * @param event the event beign handled
	 */
	public void on_button_clicked(Event event) {
		Button b = (Button)event.widget;
		number(b.getText());
	}
	
	/**
	 * This is a JGlade signal handler
	 * @param event the event beign handled
	 */
	public void on_action_button_clicked(Event event) {
		Button b = (Button)event.widget;
		action(b.getText());
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			new Demophone();
		} catch (JGladeConstructionExeption e) {
			System.err.println("Unable to create Demophone interface.");
			e.printStackTrace();
		}
	}

}

  1. package definition and imports
  2. class definition, extending JGlade
  3. widget definition
  4. constructor
  5. methods
  6. signal handlers
  7. main
Sponsored by: