Apress Pro PHP-GTK phần 9 pdf

36 354 0
Apress Pro PHP-GTK phần 9 pdf

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

CHAPTER 14 ■ USING SELECTORS & DIALOGS 295 Listing 14-8 shows a callback method that could be connected to a font button’s font-set signal to change the font of a selected region of text in a GtkTextBuffer. The font-set signal automatically passes the font button to the callback. The selected font can be returned using get_font_name. This method returns the font family, style, and size as one string. The value of get_font_name is then used to set the font property of a GtkTextTag object. This tag is then applied across the selection to modify the font of the text. Listing 14-8. A Callback for a GtkFontButton’s Font-Set Signal <?php function applyTag($fontButton, $text) { // Create a new tag to modify the text. $tag = new GtkTextTag(); // Set the tag font. $tag->set_property('font', $fontButton->get_font()); // Get the buffer. $buffer = $text->get_buffer(); // Get iters for the start and end of the selection. $selectionStart = $buffer->get_start_iter(); $selectionEnd = $buffer->get_start_iter(); // Get the iters at the start and end of the selection. $buffer->get_iter_at_mark($selectionStart, $buffer->get_insert()); $buffer->get_iter_at_mark($selectionEnd, $buffer->get_selection_bound()); // Add the tag to the buffer's tag table. $buffer->get_tag_table()->add($tag); // Apply the tag. $buffer->apply_tag($tag, $selectionStart, $selectionEnd); } ?> By default, a font button displays the font family and size of the currently selected font. The display properties of the button can be controlled. The style (bold, italic, etc.) can be added to the button’s label by passing true to set_show_style. Passing false to this method will turn the style off again. Passing false to set_show_size will hide the size in the button’s label. The size can be shown again by passing true to the same method. In addition to showing the font description, you can control the font of the button’s label. A button can be told to use the cur- rently selected font, style, or size in its label. In Figure 14-7, the GtkFontButton is told to use the font and style that has been selected. This is done using the set_use_font method. This method expects a Boolean value and changes the font and style of the button’s label if it is given true. The button’s label will not use the selected 6137ch14.qxd 3/14/06 2:33 PM Page 295 CHAPTER 14 ■ USING SELECTORS & DIALOGS296 size unless true is passed to set_use_size. Be careful when using set_use_size because the button can become unreadable or distort the appearance of the application, depending on how it is packed into its parent container. File Chooser Dialogs GtkColorSelectionDialog and GtkFontSelectionDialog are rather specialized widgets. They are most commonly used with text editing applications or pieces of an application that can edit text. GtkFileChooserDialog, on the other hand, has much broader appeal. Many different types of applications will need to access the file system in one way or another. For example, an application may need to open or save files, or an email client might need to attach a file to a message. These actions require the user to select a file and tell the application where it can be found. This is the purpose of GtkFileChooserDialog. It provides an interface for the user to browse the file system and pick one or more files. A GtkFileChooserDialog is very similar to the other selectors. It consists of a dialog window that has the top portion populated with a GtkFileChooserWidget. The action area is prepopu- lated with different buttons depending on the intended use of the dialog. When a file chooser dialog is created it expects not only a title and a parent window but also an action type. The action type defines the expected behavior of the dialog. The different types are Gtk::FILE_CHOOSE_ACTION_ OPEN, Gtk::FILE_CHOOSER_ACTION_SAVE, Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER, and Gtk::FILE_ CHOOSER_ACTION_CREATE_FOLDER. Figure 14-8 shows a save and an open file chooser dialog. The create folder and select folder dialogs are very similar in appearance. After passing the action type, the constructor for GtkFileChooserDialog expects an array of buttons and responses. These buttons and their responses will be added to the action area. Signal handlers should be created for these just as with the other selector dialogs. Just as with the other selector widgets, there is a button that makes using a file selector quite easy. GtkFileChooserButton will launch a GtkFileChooserDialog. The constructor for the button requires a title for the dialog window and an action type. A GtkFileChooserButton can only accept Gtk::FILE_CHOOSER_ACTION_OPEN and Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER as its action type. This means that a file chooser button can only be used to open files or folders. It cannot be used to save files or create folders. Figure 14-9 shows what a GtkFileChooserButton might look like in an application. To determine which filename is selected, a signal handler needs to be created for the open button of the dialog. The dialog can be accessed using the dialog property. A GtkFileChooserButton is a quick and easy way to set up a file chooser. Figure 14-7. A GtkFontButton set to use the selected font and style 6137ch14.qxd 3/14/06 2:33 PM Page 296 CHAPTER 14 ■ USING SELECTORS & DIALOGS 297 Figure 14-8. Two types of GtkFileChooserDialog Figure 14-9. A GtkFileChooserButton File Selection A GtkFileChooserDialog is a very specialized tool for allowing users to select a file. Its form and function changes depending on what the dialog will be used for. A more practical and standard approach to allow the user to select a file from the file system is to use a GtkFileSelection. This selector is much more similar to the other types of selectors we have seen so far. The interface, which can be seen in Figure 14-10, is probably more recognizable and easier to use. 6137ch14.qxd 3/14/06 2:33 PM Page 297 CHAPTER 14 ■ USING SELECTORS & DIALOGS298 Unlike the other types of selectors, there is no single class in the dialog’s vbox. Instead, the top section of the dialog is made up of several different widgets that together provide the func- tionality needed to let the user select a file. You can directly access the elements that make up both the top section and the action area. This allows for the easy creation of signal handlers. Table 14-2 shows the properties you can access in a GtkFileSelection. Table 14-2. GtkFileSelection Properties Property Description ok_button The dialog’s OK button. A signal handler should be connected to this button to get the filename. cancel_button The dialog’s cancel button. A signal handler should be connected to this button to close the dialog. fileop_c_dir A button to allow the user to create a directory. No signal handler needs to be created. fileop_del_file A button to allow the user to delete a file. No signal handler needs to be created. fileop_ren_file A button to allow the user to rename a file. No signal handler needs to be created. fileop_dialog The GtkDialog holding all the other widgets. history_pulldown A GtkOptionMenu showing the directory history. As you can see by the list of properties, a GtkFileSelection allows the user to do much more than select a file. The file operation buttons that appear at the top of the dialog can be used to create directories, delete files or directories, and rename files or directories. This amount of freedom may be undesirable in some circumstances. Therefore, these buttons can be hidden from the user by calling hide_fileop_buttons. Calling show_fileop_buttons will show these Figure 14-10. A GtkFileSelection 6137ch14.qxd 3/14/06 2:33 PM Page 298 CHAPTER 14 ■ USING SELECTORS & DIALOGS 299 buttons again. If the buttons are left visible, not much else needs to be done. The buttons come equipped with the signal handlers needed to perform their specified tasks. Of course, a new signal handler could be created if, for instance, the application wants to know when a new direc- tory is created. If the application has a tree view of the file system, knowing when a new directory is created or deleted would allow the application to know when to rebuild the under- lying model. Listing 14-9 presents the code from the Crisscott_MainWindow class. The code is used to retrieve a filename that contains the XML for an inventory. This example is only for the file open function. Saving files requires a different dialog. A GtkFileSelection is created and then run using the run method. The return value of the run method is checked to see if a file was selected. The filename is taken from the dialog using the get_filename method. If the file can- not be found, a new dialog is popped up and the open method is called again. If the filename is valid, a static method for the main window is called to load the information found in the given file. Listing 14-9. Connecting a GtkFileSelection for Opening a File <?php class Crisscott_MainWindow extends GtkWindow { // public function open() { // Create the file selection dialog. $fileSelection = new GtkFileSelection('Open'); // Make sure that only one file is selected. $fileSelection->set_select_multiple(false); // Filter the files for XML files. $fileSelection->complete('*.xml'); // Show the dialog and run it. $fileSelection->show_all(); if ($fileSelection->run() == Gtk::RESPONSE_OK) { // Make sure the file exists. if (@is_readable($fileSelection->get_filename())) { // Load the file. self::loadFile($fileSelection->get_filename()); } else { // Pop up a dialog warning // // Run this method again. self::open(); } } } } ?> 6137ch14.qxd 3/14/06 2:33 PM Page 299 CHAPTER 14 ■ USING SELECTORS & DIALOGS300 In Listing 14-9, two adjustments are made to the file selection before it is shown. First, the file selection is told not to allow multiple selections. This is done by passing false to set_select_multiple. This is really just a precaution because selection of multiple files is dis- abled by default. Next, a pattern is set using the complete method. The pattern is used to check for a possible default filename. If a file matches the pattern, it will be selected by default. If there is more than one file that matches the pattern, those files will be the only ones listed in the files list of the dialog. In Listing 14-9 the pattern is set to *.xml. This will limit the initial list of files to only XML files. About Dialogs The final dialog we will consider in this chapter is GtkAboutDialog. It presents information about the application in a pop-up window but doesn’t ask any questions. A GtkAboutDialog is normally popped up from an about menu item in the help menu. The about dialog shows information, such as the application name and version, the copyright, and the application authors. Listing 14-10 shows the code that creates the Crisscott about dialog. The end result of this code can be seen in Figure 14-11. Listing 14-10. The GtkAboutDialog for the Crisscott PIMS Application <?php class Crisscott_AboutDialog extends GtkAboutDialog { public function __construct() { // Call the parent constructor. parent::__construct(); // Set the elements of the dialog. $this->init(); } public function init() { // Set the logo image. $this->set_logo(GdkPixbuf::new_from_file('Crisscott/images/logo.png')); // Set the application name. $this->set_name('Crisscott PIMS'); // Set the copyright notice. $this->set_copyright('2005 Crisscott, Inc.'); // Set the license. $this->set_license(file_get_contents('Crisscott/license.txt')); // Set the URL to the Crisscott website. $this->set_website('http://www.crisscott.com/'); // Set the version number. $this->set_version('1.0.0'); // Set the description of the application. 6137ch14.qxd 3/14/06 2:33 PM Page 300 CHAPTER 14 ■ USING SELECTORS & DIALOGS 301 $this->set_comments('An application to manage product information ' . 'for distribution through Crisscott.com'); } } ?> The preceding listing sets the many different parts of the about dialog. The first thing that is set is the logo. The logo is set with set_logo that expects a GdkPixbuf as the only argument. Next, the name of the application is set using set_name. The copyright information is set using set_copyright. The license is set using set_license. The copyright and license methods expect a string as the only argument. There are several different pieces of information that can be set and each has its own method: • set_name: Sets the name of the application. • set_copyright: Sets the copyright notice. • set_comments: Adds a description of the application. • set_license: Adds a line describing the license the application is released under. It adds a button to the dialog that opens another window with the contents of the license. • set_website: Can be used to add a URL where more information can be found. • set_website_label: Sets a string used as the text for the website link. If no label is set, the link defaults to the URL. • set_authors: Adds each author in the given array to the list of authors. • set_artists: Adds each artist in the given array to the list of artists. • set_documenters: Adds each documenter in the given array to the list of documenters. • set_translator_credits: Adds a line for the translator who worked on the current language version. Figure 14-11. The Crisscott about dialog 6137ch14.qxd 3/14/06 2:33 PM Page 301 CHAPTER 14 ■ USING SELECTORS & DIALOGS302 Summary Dialogs and selectors allow large functional components to be hidden until needed. These components can be used to confirm a user’s action or to gather more complicated information, such as colors, fonts, and filenames. Using a dialog is a simple matter of showing the dialog and connecting the needed signal handlers. In some cases, it is possible to automate the process using a specially designed button. Color, font, and file selectors have buttons that can open up the dialog and connect most of the signal handlers. When a button is used, normally, only one signal handler needs to be created. This signal handler can then return the needed value. Dialogs and selectors are the last major functional widgets I will talk about. Chapter 15 talks about doing work in the background. It will show how to allow the user to continue working while an application does other work. You will also see how to report the progress of background tasks using progress bars. Finally, you will see how to repeat tasks over an interval of time. Chapter 15 makes the Crisscott PIMS application more automated. 6137ch14.qxd 3/14/06 2:33 PM Page 302 303 CHAPTER 15 ■ ■ ■ Doing Background Work Atypical Web-based application uses a very rigid process for communicating with the user. The user makes a request and the server sends a response. In a Web-based application the server can’t initiate contact with the user, whereas a GUI application can notify the user when an event has occurred. This simple distinction allows for one of the more interesting features of PHP-GTK: background work. Background work goes on while the user is working on something else, allowing for much greater efficiency. Contrast this with a Web application where the user must wait for each, often time-consuming, process. For example, consider a travel website. When a user submits a search request for airline tickets, normally a graphic is loaded asking the user to be patient while the search is conducted. Until the user is taken to the results page, he or she can’t access any other information. But in a GUI application, long running processes can occur behind the scenes while the user continues to work. When the process is finished, the application can notify the user. In this chapter we will see how to allow the user to continue working while the application is doing work in the background. Progress Bars Before discussing the details of how an application can perform background work, it is a good idea to discuss how the user will be notified of the application’s progress. One method, as we have seen with the splash screen, is to offer continuously updated messages in the interface. Another method is to use a progress bar. GtkProgressBar is a widget designed to keep the user informed about the status of a long running process. The process can be anything that has a definite beginning and end, such as uploading a file, writing information to a database, or even collecting information from the user in several steps. If the progress of something can be measured, then a GtkProgressBar can relay that information to the user. Progress bars can be used to display information about two distinct types of processes: • Progress mode: This mode describes a process where the amount of work completed, as well as the total amount of work to be completed, is known. To tell the user how much work has been done and how much work is left to do, the progress bar grows from one end to the other. • Activity mode: This mode can only tell the user that work is in progress. When the progress bar is in activity mode, the bar bounces back and forth. Activity mode is useful if, for example, the application is waiting for a response from a remote server. 6137ch15.qxd 3/14/06 2:34 PM Page 303 CHAPTER 15 ■ DOING BACKGROUND WORK304 Figure 15-1. A GtkProgressBar in progress mode and in activity mode Figure 15-1 shows an example of each type of progress bar. Creating a Progress Bar Creating a progress bar is a simple matter of using the new operator, regardless of the type of progress bar you need. The type of progress bar that is used is decided at runtime and is dependent upon which GtkProgressBar method is called. For progress mode, the set_fraction method is called. With set_fraction a fraction of the progress bar between zero and one (inclusive) is filled. When called repeatedly, set_fraction makes the progress bar appear to grow or shrink from one end to the other. You can put a progress bar into activity mode by calling the pulse method, which takes no arguments. This method moves the bar one pulse step, which is the relative distance the activity indicator will travel with each pulse. The pulse step can be set using the appropriately named set_pulse_step method. This method takes one argument, which is similar to the value passed to set_fraction. The value passed to set_pulse_step must be a number between zero and one (inclusive) and will determine how far the indicator will move with each pulse. For example, if the value passed to set_pulse_step is .2, each pulse will cause the indicator to move one-fifth of the total length of the progress bar. After five pulses, the indicator would reach the end of the progress bar. The next pulse will cause the indicator to move one-fifth of the way back toward the beginning of the progress bar. ■Note If there is not a full step between the indicator and the end of the progress bar, the indicator will only move to the end of the progress bar. It will not rebound in the opposite direction in a single step. Listing 15-1 is a class that sends product data to the Crisscott server using a SOAP interface. In this class, data is transmitted one product at a time. This allows the method to know how much work has been done and to update the progress bar after sending the data for each product. The progress bar will be displayed in progress mode because the set_fraction method is being called. Notice also the call to the set_text method of the progress bar. The set_text method superimposes text over the progress bar. The text appears centered over the entire progress bar, not just the portion that has been filled in. Listing 15-1. Creating and Updating a GtkProgressBar <?php class Crisscott_Tools_ProgressDialog extends GtkDialog { public $progress; 6137ch15.qxd 3/14/06 2:34 PM Page 304 [...]... Add a progress bar $this->progress = new GtkProgressBar(); $this->vbox->pack_start($this->progress); } } class Crisscott_Inventory { // public static function transmitInventory() { // Create a SOAP client require_once 'Crisscott/SOAPClient.php'; $soap = new Crisscott_SOAPClient(); // Collect all of the products $products = self::getAllProducts(); // Create a progress dialog for showing the progress... the products if (empty(self::$products)) { self::getAllProducts(); } // Create a progress dialog for showing the progress (From Listing 15-1) require_once 'Crisscott/Tools/ProgressDialog.php'; $dialog = Crisscott_Tools_ProgressDialog::singleton('Sending Inventory'); // Show the progress dialog $dialog->show_all(); // We need to know the total to know the percentage complete $total = count(self::$products);... // Loop through the products in each category foreach ($category->products as $product) { $products[] = $product; } } return $products; } } ?> In this example, the text is used as another way to communicate with the user The superimposed text shows the percentage of the work completed It doesn’t have to simply reiterate the progress; it could be a string that identifies what the progress bar is indicating... 'Crisscott/Tools/ProgressDialog.php'; $dialog = new Crisscott_Tools_ProgressDialog('Sending Inventory'); // Show the progress dialog $dialog->show_all(); // Set a flag that indicates transmission has started self::$transmitting = true; // We need to know the total to know the percentage complete $total = count($products); // Transmit each product one at a time foreach ($products as $key => $product) { $soap->sendProduct($product);... 'Crisscott/Tools/ProgressDialog.php'; $dialog = new Crisscott_Tools_ProgressDialog('Sending Inventory'); // Show the progress dialog $dialog->show_all(); // We need to know the total to know the percentage complete $total = count($products); // Transmit each product one at a time foreach ($products as $key => $product) { 305 6137ch15.qxd 306 3/14/06 2:34 PM Page 306 CHAPTER 15 ■ DOING BACKGROUND WORK $soap->sendProduct($product);... count(self::$products); // Transmit the current product $soap->sendProduct(self::$products[self::$currentProduct]); // Update the progress bar $percentComplete = (++self::$currentProduct) / $total; $dialog->progress->set_fraction($percentComplete); // Display the percentage as a string over the bar $percentComplete = round($percentComplete * 100, 0); $dialog->progress->set_text($percentComplete '%'); 311... there are more products to send $count = count(self::$products); if (self::$products[self::$currentProduct] == self::$products[$count – 1]) { $dialog->destroy(); return false; } else { return true; } } public static function getAllProducts() { self::$products = array(); // Loop through categories in the inventory foreach (self::$instance->categories as $category) { // Loop through the products in each... indicates products are being transmitted static public $transmitting = false; public static function transmitInventory() { // Create a SOAP client require_once 'Crisscott/SOAPClient.php'; $soap = new Crisscott_SOAPClient(); 6137ch15.qxd 3/14/06 2:34 PM Page 3 09 CHAPTER 15 ■ DOING BACKGROUND WORK // Collect all of the products $products = self::getAllProducts(); // Create a progress dialog for showing the progress... transmitInventory method is called, a new product is sent to the server When all the products have been sent, transmitInventory returns false The method returns true while there are still products that haven’t been sent Listing 15-4 Breaking Up transmitInventory to Send One Product at a Time . BACKGROUND WORK 3 09 // Collect all of the products. $products = self::getAllProducts(); // Create a progress dialog for showing the progress. require_once 'Crisscott/Tools/ProgressDialog.php'; $dialog. complete. $total = count($products); // Transmit each product one at a time. foreach ($products as $key => $product) { $soap->sendProduct($product); // Update the progress bar. $percentComplete. count(self::$products); // Transmit the current product. $soap->sendProduct(self::$products[self::$currentProduct]); // Update the progress bar. $percentComplete = (++self::$currentProduct) /

Ngày đăng: 07/08/2014, 00:22

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan