PHP CookBook Free Open Book

PHP CookBook

Previous Section Next Section

Recipe 20.11 Program: Displaying Weather Conditions

The gtk-weather.php program shown in Example 20-2 uses SOAP and a weather web service to display weather conditions around the world. It incorporates a number of GTK widgets in its interface: menus, keyboard accelerators, buttons, a text entry box, labels, scrolled windows, and columned lists.

To use gtk-weather.php, first search for weather stations by typing a search term in the text-entry box and clicking the Search button. Searching for weather stations is shown in Figure 20-4.

Figure 20-4. Searching for weather stations
figs/phpc_2004.gif

Once you've retrieved a list of weather stations, you can get the conditions at a specific station by selecting the station and clicking the Add button. The station code and its current conditions are added to the list at the bottom of the window. You can search again and add more stations to the list. The gtk-weather.php window with a few added stations is shown in Figure 20-5.

Figure 20-5. Added weather stations
figs/phpc_2005.gif

The web service this program uses is called GlobalWeather; look for more information about it at http://www.capescience.com/webservices/globalweather/index.shtml.

Example 20-2. gtk-weather.php
// Load the GTK extension
dl('php_gtk.'. (((strtoupper(substr(PHP_OS,0,3))) == 'WIN')?'dll':'so'));

// Load the SOAP client class
require 'SOAP/Client.php';

// Create the main window and set its title and size
$window = &new GtkWindow();
$window->set_title('PHP Cookbook GTK Demo');
$window->set_default_size(500,200);

// The main layout container for the window is a VBox
$vbox = &new GtkVBox();
$window->add($vbox);

// Create a GtkAccelGroup to hold keyboard accelerators
$accelgroup = &new GtkAccelGroup();
$window->add_accel_group($accelgroup);

// Build the menu, starting with the GtkMenuBar. The arguments to 
// pack_start() prevent the menu bar from expanding if the window does.
$menubar = &new GtkMenuBar();
$vbox->pack_start($menubar, false, false);

// Create the "File" menu and its keyboard accelerator
$menu_file_item = &new GtkMenuItem('_File');
$menu_file_item_label = $menu_file_item->child;
$menu_file_item->add_accelerator('activate',$accelgroup,
                                 $menu_file_item_label->parse_uline('_File'),
                                 GDK_MOD1_MASK,0);
// Add the "File" menu to the menu bar
$menubar->add($menu_file_item);

// Create the submenu for the options under "File"
$menu_file_submenu = &new GtkMenu();
$menu_file_item->set_submenu($menu_file_submenu);

// Create the "Quit" option under "File" and its accelerator
// GDK_MOD1_MASK means that the accelerator is Alt-Q, not Q
// GTK_ACCEL_VISIBLE means that the accelerator is displayed in the menu
$menu_file_choices_quit = &new GtkMenuItem('_Quit');
$menu_file_choices_quit_label = $menu_file_choices_quit->child;
$menu_file_choices_quit->add_accelerator('activate',$accelgroup,
    $menu_file_choices_quit_label->parse_uline('_Quit'),GDK_MOD1_MASK,
    GTK_ACCEL_VISIBLE);

// Add the "File | Quit" option to the "File" submenu
$menu_file_submenu->append($menu_file_choices_quit);

// Create the "Help" menu and its keyboard accelerator
$menu_help_item = &new GtkMenuItem('_Help');
$menu_help_item_label = $menu_help_item->child;
$menu_help_item->add_accelerator('activate',$accelgroup,
                                 $menu_help_item_label->parse_uline('_Help'),
                                 GDK_MOD1_MASK,0);
// Add the "Help" menu to the menu bar
$menubar->add($menu_help_item);

// Create the submenu for the options under "Help"
$menu_help_submenu = &new GtkMenu();
$menu_help_item->set_submenu($menu_help_submenu);

// Create the "About" option under "Help" and its accelerator
$menu_help_choices_about = &new GtkMenuItem('_About');
$menu_help_choices_about_label = $menu_help_choices_about->child;
$menu_help_choices_about->add_accelerator('activate',$accelgroup,
    $menu_help_choices_about_label->parse_uline('_About'),GDK_MOD1_MASK,
    GTK_ACCEL_VISIBLE);

// Add the "Help | About" option to the "Help" submenu
$menu_help_submenu->append($menu_help_choices_about);

// Layout the weather station searching widgets in a GtkTable
$table_1 = &new GtkTable(2,4);
$vbox->pack_start($table_1);

// Put a label on the left in the first row
$label_sn = &new GtkLabel('Station Name: ');
$label_sn->set_alignment(1,0.5);
$table_1->attach($label_sn,0,1,0,1, GTK_FILL);

// Put a text entry field in the middle of the first row
// The accelerator allows you to hit "Return" in the field to submit
$entry_sn = &new GtkEntry();
$entry_sn->add_accelerator('activate',$accelgroup,GDK_KEY_Return,0,0);
$table_1->attach($entry_sn,1,2,0,1, GTK_FILL);

// Put a scrolled window in the second row of the table
$scrolledwindow_1 = &new GtkScrolledWindow();
$scrolledwindow_1->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
$table_1->attach($scrolledwindow_1,0,4,1,2, GTK_EXPAND | GTK_SHRINK | GTK_FILL,
                 GTK_EXPAND | GTK_SHRINK | GTK_FILL);

// Put a columned list in the scrolled window. By putting the list inside
// the scrolled window instead of directly in the GtkTable, the window doesn't
// have to grow to a huge size to let you see everything in the list
$clist_sn = &new GtkCList(4,array('Code','Name','Region','Country'));
$scrolledwindow_1->add($clist_sn);

// Set the columns in the list to resize automatically
for ($i = 0; $i < 4; $i++) { $clist_sn->set_column_auto_resize($i,true); }

// Add a "Search" button to the first row
$button_search =&new GtkButton('Search');
$table_1->attach($button_search,2,3,0,1, GTK_FILL);

// Add an "Add" button to the first row
$button_add = &new GtkButton('Add');
$table_1->attach($button_add,3,4,0,1, GTK_FILL);

// Layout the weather conditions display widgets in another GtkTable
$table_2 = &new GtkTable(2,3);
$vbox->pack_start($table_2);

// Add a label displaying how many stations are shown
$label_st = &new GtkLabel('Stations: 0');
$label_st->set_alignment(0,0.5);
$table_2->attach($label_st,0,1,0,1, GTK_FILL);

// Add a button to update a single station
$button_update_sel = &new GtkButton('Update Selected');
$table_2->attach($button_update_sel,1,2,0,1, GTK_FILL);

// Add a button to update all stations
$button_update_all = &new GtkButton('Update All');
$table_2->attach($button_update_all,2,3,0,1, GTK_FILL);

// Add a columned list to hold the weather conditions at the stations
// This columned list also goes inside a scrolled window
$scrolledwindow_2 = &new GtkScrolledWindow();
$scrolledwindow_2->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
$table_2->attach($scrolledwindow_2,0,3,1,2, GTK_EXPAND | GTK_SHRINK | GTK_FILL,
                 GTK_EXPAND | GTK_SHRINK | GTK_FILL);
$clist_st = &new GtkCList(5,array('Code','Temp','Precipitation','Wind','Updated'));
$scrolledwindow_2->add($clist_st);

// Set the columns in the list to resize automatically
for ($i = 0; $i < 5; $i++) { $clist_st->set_column_auto_resize($i,true); }

// Connect signals to callbacks

// Clicking on the "Search" button or hitting Return in the text entry field
// searches for weather stations whose name match the entered text
$button_search->connect('clicked','wx_searchByName',$entry_sn,$clist_sn,$window);
$entry_sn->connect('activate','wx_searchByName',$entry_sn,$clist_sn,$window);

// Clicking on the "Add" button adds the weather station to the bottom 
// columned list
$button_add->connect('clicked','cb_add_station',$clist_sn,$clist_st,$label_st);

// Clicking on the "Update Selected" button updates the bottom columned list
// for a single station
$button_update_sel->connect('clicked','wx_update_report',$clist_st,$label_st,
                            'selected');
// Clicking on the "Update All" button updates all stations in the bottom
// columned list
$button_update_all->connect('clicked','wx_update_report',$clist_st,$label_st,
                            'all');

// Closing the window or selecting the "File | Quit" menu item exits the program
$window->connect('destroy','cb_shutdown');
$menu_file_choices_quit->connect('activate','cb_shutdown');

// Selecting the "Help | About" menu item shows an about box
$menu_help_choices_about->connect('activate','cb_about_box',$window);

// These callbacks keep track of the currently selected row (if any)
// in each columned list
$clist_sn->connect('select-row','cb_clist_select_row');
$clist_sn->connect('unselect-row','cb_clist_unselect_row');
$clist_st->connect('select-row','cb_clist_select_row');
$clist_st->connect('unselect-row','cb_clist_unselect_row');

// The interface has been set up and the signals we want to pay attention
// to have been connected to callbacks. Time to display the window and start
// the GTK signal handling loop.
$window->show_all();
gtk::main();

/*
 * CALLBACKS AND OTHER SUPPORT FUNCTIONS
 */

// use the searchByName() function over SOAP to get a list of stations
// whose names match the given search term
function wx_searchByName($button,$entry,$clist,$window) {
    // instantiate a new SOAP client
    $sc = new SOAP_Client('http://live.capescience.com/ccx/GlobalWeather');

    $search_term = trim($entry->get_text());
    if ($search_term) {
        // call the remote function if a search term is provided
        $res = $sc->call('searchByName',
                         array(new SOAP_Value('name','string',$search_term)),
                         'capeconnect:GlobalWeather:StationInfo',
                         'capeconnect:GlobalWeather:StationInfo#searchByName');

        // pop up an error dialog if the SOAP function fails
        if (PEAR::isError($res)) {
            error_dialog($res->getMessage(),$window);
            return false;
        }
        // pop up an error dialog if there are no matches
        if (! is_array($res)) {
            error_dialog('No weather stations found.',$window);
            return false;
        }
        // add each station and its info to the columned list
        // wrapping the calls to append() with freeze() and thaw()
        // make all of the data appear at once
        $clist->freeze();
        $clist->clear();
        foreach ($res as $station) {
            $clist->append(array($station->icao,$station->name,
                                 $station->region,$station->country));
        }
        $clist->thaw();
    } 
}

// use the getWeatherReport function over SOAP to get the weather conditions
// at a particular station
function wx_getWeatherReport($code) {
    $sc = new SOAP_Client('http://live.capescience.com/ccx/GlobalWeather');
    $res = $sc->call('getWeatherReport',
                     array(new SOAP_Value('code','string',$code)),
                     'capeconnect:GlobalWeather:GlobalWeather',
                     'capeconnect:GlobalWeather:GlobalWeather#getWeatherReport');

    if (PEAR::isError($res)) {
        error_dialog($res->getMessage());
        return false;
    } else {
        return $res;
    }
}

// add the weather report in $res to the columned list $clist
// if $row is null, the report is appended to the list
// if $row is not null, the report replaces row $row in the list
function wx_add_report($clist,$label,$res,$row = null) {

    // format the timestamp
    $timestamp = str_replace('T',' ',$res->timestamp);
    $timestamp = str_replace('Z',' GMT',$timestamp);
    $timestamp = strftime('%H:%M:%S %m/%d/%Y',strtotime($timestamp));

    // format the wind information
    $wind = sprintf("%.2f m/s from %s",
                    $res->wind->prevailing_speed,
                    $res->wind->prevailing_direction->compass);
        
    $clist->freeze();
    if (! is_null($row)) {
        // replace the information in row number $row
        $clist->set_text($row,1,$res->temperature->string);
        $clist->set_text($row,2,$res->precipitation->string);
        $clist->set_text($row,3,$wind);
        $clist->set_text($row,4,$timestamp);
    } else {
        // add the information to the end of the columned list
        $clist->append(array($res->station->icao,
                             $res->temperature->string,
                             $res->precipitation->string,
                             $wind,
                             $timestamp));

        // update the columned list's internal row count
        $rows = 1 + $clist->get_data('rows');
        $clist->set_data('rows',$rows);
        // update the label that displays a station count
        $label->set_text("Stations: $rows");
    }
    $clist->thaw();
}

// update conditions for one station or all stations, depending on $mode
function wx_update_report($button,$clist,$label,$mode) {
    switch ($mode) {
    case 'selected':

        // if there is a row selected
        $selected_row = $clist->get_data('selected_row');
        if (($selected_row >= 0) && (! is_null($selected_row))) {
            $code = $clist->get_text($selected_row,0);
            
            // get the report and update the columned list
            if ($res = wx_getWeatherReport($code)) {
                wx_add_report($clist,$label,$res,$selected_row);
            } 
        }
        break;
    case 'all':
        // for each row in the columned list
        for ($i = 0, $j = $clist->get_data('rows'); $i < $j; $i++) {
            // get the report and update the list
            if ($res = wx_getWeatherReport($clist->get_text($i,0))) {
                wx_add_report($clist,$label,$res,$i);
            }
        }
        break;
    }
}

// add a station to the bottom list of weather reports
function cb_add_station($button,$clist,$clist_2,$label) {
    $selected_row = $clist->get_data('selected_row');
    // if there's a selected row in the top list of stations
    if ($selected_row >= 0) {
        $code = $clist->get_text($selected_row,0);
        // get the weather report for that station
        if ($res = wx_getWeatherReport($code)) {
            // find the row if this code is already in the list
            $row = null;
            for ($i = 0, $j = $clist_2->get_data('rows'); $i < $j; $i++) {
                if ($clist_2->get_text($i,0) == $code) {
                    $row = $i;
                }
            }
            // add the station and its report to the bottom list of
            // reports (or update the existing row)
            wx_add_report($clist_2,$label,$res,$row);
        } 
    }
}

// update a columned list's internal selected row value when a row is selected
function cb_clist_select_row($clist,$row,$col,$e) {
    $clist->set_data('selected_row',$row);
}

// clear a columned list's internal selected row value when a row is unselected
function cb_clist_unselect_row($clist) {
    $clist->set_data('selected_row',-1);
}

// display the "About Box"
function cb_about_box($menu_item,$window) {
    $about_box = &new GtkDialog();
    $vbox = $about_box->vbox;
    $action_area = $about_box->action_area;
    $about_box->set_title('About');
    $label = &new GtkLabel("This is the PHP Cookbook PHP-GTK Demo.");
    $button = &new GtkButton('OK');
    $button->connect('clicked','cb_dialog_destroy',$about_box);
    $vbox->pack_start($label);
    $action_area->pack_start($button);
    $about_box->set_modal(true);
    $about_box->set_transient_for($window);
    $about_box->show_all();
}

// display an error dialog box
function error_dialog($msg,$window) {
    $dialog = &new GtkDialog();
    $vbox = $dialog->vbox;
    $action_area = $dialog->action_area;
    $dialog->set_title('Error');
    $label = &new GtkLabel("Error: $msg");
    $button = &new GtkButton('OK');
    $button->connect('clicked','cb_dialog_destroy',$dialog);
    $vbox->pack_start($label);
    $action_area->pack_start($button);
    $dialog->set_modal(true);
    $dialog->set_transient_for($window);
    $dialog->show_all();
}

// close a dialog box
function cb_dialog_destroy($button,$dialog) {
    $dialog->destroy();
}

// quit the main program
function cb_shutdown() { gtk::main_quit(); }

    Previous Section Next Section
    Index: [SYMBOL][A][B][C][D][E][F][G][H][I][J][K][L][M][N][O][P][Q][R][S][T][U][V][W][X][Z]


         Main Menu
    Main Page
    Table of content
    Copyright
    Preface
    Chapter 1. Strings
    Chapter 2. Numbers
    Chapter 3. Dates and Times
    Chapter 4. Arrays
    Chapter 5. Variables
    Chapter 6. Functions
    Chapter 7. Classes and Objects
    Chapter 8. Web Basics
    Chapter 9. Forms
    Chapter 10. Database Access
    Chapter 11. Web Automation
    Chapter 12. XML
    Chapter 13. Regular Expressions
    Chapter 14. Encryption and Security
    Chapter 15. Graphics
    Chapter 16. Internationalization and Localization
    Chapter 17. Internet Services
    Chapter 18. Files
    Chapter 19. Directories
    Chapter 20. Client-Side PHP
    20.1 Introduction
    Recipe 20.2 Parsing Program Arguments
    Recipe 20.3 Parsing Program Arguments with getopt
    Recipe 20.4 Reading from the Keyboard
    Recipe 20.5 Reading Passwords
    Recipe 20.6 Displaying a GUI Widget in a Window
    Recipe 20.7 Displaying Multiple GUI Widgets in a Window
    Recipe 20.8 Responding to User Actions
    Recipe 20.9 Displaying Menus
    Recipe 20.10 Program: Command Shell
    Recipe 20.11 Program: Displaying Weather Conditions
    Chapter 21. PEAR
    Colophon
    Index


    More Books
    PHP Hacks
    Processing Xml With Java - A Guide To Sax, Dom, Jdom, Jaxp, And Trax
    The Koran (Holy Qur'an)
    Macromedia Flash 8 Bible
    Search Engine Optimization for Dummies
    YouTube Traffic
    PHP 5 for Dummies
    Harry Potter and The Chamber of Secrets
    Harry Potter and the Sorcerer's Stone
    The Pilgrim's Progress
    Wireless Hacks
    Flash Hacks. 100 Industrial-Strength Tips & Tools
    PayPal Hacks. 100 Industrial-Strength Tips and Tools
    Amazon Hacks
    Pdf Hacks
    The Da Vinci Code
    Google Hacks
    The Holy Bible
    Windows XP For Dummies
    Harry Potter and the Half-Blood Prince
    Seo Book
    Upgrading and Repairing Networks
    Macromedia Dreamweaver 8 UNLEASHED
    Windows XP Annoyances
    Windows XP Hacks
    Microsoft Windows XP Power Toolkit
    Teach Yourself MS Office In 24Hours
    iPod & iTunes Missing Manual
    PC Hacks 100 Industrial-Strength Tips and Tools
    PC Overclocking, Optimization, and Tuning - 2th Edition
    PC Hardware In A Nutshell 3rd Edition
    PC Hardware in a Nutshell, 2nd Edition
    Upgrading and Repairing PCs
    Google for Dummies
    MySQL Cookbook
    Teach Yourself Macromedia Flash 8 In 24 Hours
    PHP CookBook
    Sams Teach Yourself JavaScript in 24 Hours
    PHP5 Manual
    Free Games Paper Airplanes
    500 Juegos Gratis 500 Giochi Gratis 500 Jeux Gratuits 500 Jogos Gratis 500 Kostenlose Spiele