1. Trang chủ
  2. » Công Nghệ Thông Tin

Apress Pro PHP-GTK phần 7 docx

40 271 0

Đ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

Nội dung

CHAPTER 9 ■ WORKING WITH TREES AND LISTS218 // Get the singleton product summary. require_once 'Crisscott/Tools/ProductSummary.php'; $productSummary = Crisscott_Tools_ProductSummary::singleton(); $productSummary->displaySummary($product); } public static function singleton() { if (!isset(self::$instance)) { $class = __CLASS__; self::$instance = new $class; } return self::$instance; } } ?> Summary Trees and lists by themselves are relatively simple objects for modeling, rather than complex data structures. A tree or list can take a collection of data and make it easy to navigate and access individual elements. The organized nature of these models allows them to be used in a myriad of ways when combined with GtkTreeView and its associated objects. The specializa- tion and abstraction of responsibility of these classes make for a very powerful tool set that can provide almost endless flexibility when it comes to how a model should be displayed and accessed. Now that you have seen how to work with large collections of data, you’ll want to know how to display all of that data in a small space. Chapter 10 discusses how to make a section of an application scroll so that the user can access data that cannot fit in the space given for a tool. No longer will the sections of the application be restricted by the size of a container or the user’s screen. An endless amount of space will be made available for any piece of the application that needs it by providing scrollbars for both the horizontal and vertical axes. 6137ch09.qxd 3/14/06 2:14 PM Page 218 219 CHAPTER 10 ■ ■ ■ Scrolling At this point, the Crisscott PIMS application has several tools that may contain large amounts of data. Unfortunately, none of them currently provides a graceful way to handle this data when it exceeds the boundaries of the tool. For instance, if the data contained within the product tree exceeds the space provided by the tree, rows and characters just get pushed out of the visible area. Other tools may stretch to accommodate the oversized data. While this approach doesn’t hide data from the user, it can interfere with the layout of the rest of the application, which may be more damaging than hiding values. A better solution enables a tool to extend its data beyond its visible borders, but remain accessible to the users. This is the role of scrolling widgets. GtkScrolledWindow and GtkViewPort are widgets specifically designed to make data accessi- ble even though it has outgrown its available space within the application. These two widgets provide a means to access data in another widget that is not currently within the widget’s visi- ble area. Additionally, you can customize scrolling for a particular widget. Throughout this chapter, we will examine ways to use scrolling to make better use of the space available in the PIMS application. Scrolled Windows Some widgets have been designed with scrolling in mind. These widgets, including GtkTreeView and GtkTextView, will likely display large amounts of data. For example, a tree or list could show many rows from a database. A GtkTextView widget may display a lengthy press release or report. In order to make either of those documents fit on one screen, the font would have to be very small, likely rendering the document unreadable. Instead of asking developers to squeeze data into a restricted space, the designers of these widgets have given them native scrolling support. Native scrolling support means that the widgets can accept scrollbars and will allow the scrollbars to control which part of the widget is shown in the visible area. GtkScrolledWindow provides the scrollbars that these widgets need. GtkScrolledWindow is a bin container, a descendant of GtkBin. The scrollbars that it provides make it easier for users to access different parts of the child widget. For instance, consider Figure 10-1, which depicts the product tree without scrollbars. It is impossible to see all the rows of the tree at once, and there is nothing to indicate to the user that the contents of the view are scrollable. 6137ch10.qxd 3/14/06 2:16 PM Page 219 CHAPTER 10 ■ SCROLLING220 Figure 10-1. A GtkTreeView without scrollbars Figure 10-2. A GtkTreeView with scrollbars On the other hand, Figure 10-2 displays the product tree after it has been added to a GtkScrolledWindow. While this doesn’t make it possible to see all the rows at once (actually, the scrollbars take up space, making even less information visible), it does make it clear that the contents of the window can be scrolled. Adding scrollbars to those widgets that have native scrollbar support is relatively easy. Listing 10-1 presents an excerpt from an updated version of the Crisscott_MainWindow class. In previous iterations of this class, the Crisscott_Tools_ProductTree instance was attached directly to the table. In this example, the instance is added to a GtkScrolledWindow, which is then attached to the table. Listing 10-1. Adding Scrollbars to a GtkTreeView <?php // // Get a singleton instance of the product tree. require_once 'Crisscott/Tools/ProductTree.php'; $productTree = Crisscott_Tools_ProductTree::singleton(); 6137ch10.qxd 3/14/06 2:16 PM Page 220 CHAPTER 10 ■ SCROLLING 221 // Create a scrolled window for the product tree. $scrolledWindow = new GtkScrolledWindow(); // Set the size of the scrolled window. $scrolledWindow->set_size_request(150, 150); // Set the scrollbar policy. $scrolledWindow->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); // Add the product tree to the scrolled window. $scrolledWindow->add($productTree); // Attach the scrolled window to the tree. $table->attach($scrolledWindow, 0, 1, 2, 3, 0, $expandFill, 0, 0); // ?> Notice that the scrolled window, rather than the product tree instance, is sized. This is because the scrollbars are added to the outside of the scrolled window’s child widget. If the product tree were sized to 150 pixels wide and then added to the scrolled window, the layout of the application would be distorted. In the simplest scrolling use case, adding the child is all that needs to be done. But, as you can see in Listing 10-1, some customizations may be made. Setting the Scrollbar Policy One of the most common customizations for a GtkScrolledWindow is setting the scrollbar policy. The scrollbar policy determines when scrollbars will appear in the scrolled window. The default is to always show both the horizontal and vertical scrollbars, but this can be changed. Three policy rules can be applied to horizontal and vertical scrollbars individually: • Gtk::POLICY_ALWAYS: The scrollbar should be shown, regardless of whether or not there is enough information to scroll in the given direction. • Gtk::POLICY_AUTOMATIC: The scrolled window shows the scrollbar only when it is needed. • Gtk::POLICY_NEVER: The scrollbar will never be shown. You can set the policies for a scrolled window with set_policy. The first argument that set_policy expects is the policy for the horizontal scrollbar, and the second argument is for the vertical scrollbar. The code in Listing 10-1 sets the policy for the horizontal scrollbar to Gtk::POLICY_NEVER, while the vertical scrollbar is set to Gtk::POLICY_AUTOMATIC. The horizontal scrollbar is not needed because the cell renderer for the tree is told to ellipsize the cell text. Even if the policy were set to automatic, the scrollbar would never be shown because the child widget will not expand horizontally. Not only is it possible to set whether the scrollbars appear in a GtkScrolledWindow, but you can also control where they appear in relation to the child widget. 6137ch10.qxd 3/14/06 2:16 PM Page 221 Figure 10-3. Different child placements in a GtkScrolledWindow Controlling Child Placement Technically speaking, the position of the scrollbars is not changeable, but the placement of the child can be controlled. You can position the child in one of four places relative to the scroll- bars: Gtk::CORNER_TOP_LEFT (the default), Gtk::CORNER_TOP_RIGHT, Gtk::CORNER_BOTTOM_LEFT, and Gtk::CORNER_BOTTOM_RIGHT. Figure 10-3 shows the effect each of these placements has on a scrolled window. CHAPTER 10 ■ SCROLLING222 Setting the placement is a simple matter of passing one of the position types to set_placement. Listing 10-2 shows the code that was used to create Figure 10-3. Listing 10-2. Setting Child Placements in a GtkScrolledWindow <?php // Create and set up a window. $window = new GtkWindow(); $window->connect_simple('destroy', array('gtk', 'main_quit')); // Add a table to the window. $table = new GtkTable(2, 2); $window->add($table); // Create four scrolled windows. $sw1 = new GtkScrolledWindow(); $sw2 = new GtkScrolledWindow(); $sw3 = new GtkScrolledWindow(); $sw4 = new GtkScrolledWindow(); // Set each window to a different position. $sw1->set_placement(Gtk::CORNER_TOP_LEFT); $sw2->set_placement(Gtk::CORNER_TOP_RIGHT); $sw3->set_placement(Gtk::CORNER_BOTTOM_LEFT); $sw4->set_placement(Gtk::CORNER_BOTTOM_RIGHT); // Create four frames. $frame1 = new GtkFrame('TOP_LEFT'); 6137ch10.qxd 3/14/06 2:16 PM Page 222 Figure 10-4. Different shadow types in a GtkScrolledWindow CHAPTER 10 ■ SCROLLING 223 $frame2 = new GtkFrame('TOP_RIGHT'); $frame3 = new GtkFrame('BOTTOM_LEFT'); $frame4 = new GtkFrame('BOTTOM_RIGHT'); // Add the scrolled windows to the frames. $frame1->add($sw1); $frame2->add($sw2); $frame3->add($sw3); $frame4->add($sw4); // Attach the frames to the table. $table->attach($frame1, 0, 1, 0, 1); $table->attach($frame2, 1, 2, 0, 1); $table->attach($frame3, 0, 1, 1, 2); $table->attach($frame4, 1, 2, 1, 2); // Show everything. $window->show_all(); gtk::main(); ?> In this example, four scrolled windows are created and added to four frames. Each frame is then attached to a table. Each of the four frames is given a different placement by calling set_placement. Along with set_policy, set_placement gives a great degree of control over how and where scrollbars appear in a scrolled window. Setting a Shadow The final customization that you can make to a GtkScrolledWindow is to set a shadow around the child widget. Setting a shadow around a scrolled window’s child widget helps it to stand out a little from the rest of the application. You can set the shadow by using set_shadow_type and passing a shadow type constant. These constants are the same as the constants used to set the border on a frame: Gtk::SHADOW_ IN, Gtk::SHADOW_OUT, Gtk::SHADOW_ETCHED_IN, and Gtk::SHADOW_ETCHED_OUT. Figure 10-4 shows what each of these shadow types looks like. As you can see from the different windows, the name of the shadow type refers to the position of the window, not the scrollbars. 6137ch10.qxd 3/14/06 2:16 PM Page 223 CHAPTER 10 ■ SCROLLING224 View Ports Just because a widget doesn’t have native scrollbar support doesn’t mean that it can’t be scrolled. Widgets other than GtkTreeView and GtkTextView can extend over their bounds. Containers in particular tend to expand more than the developers originally intended. Unfortunately, widgets without native scrollbar support cannot be added to a GtkScrolledWindow. That is where GtkViewPort steps in. GtkViewPort is a widget that has native scrollbar support, designed to hold other widgets and make them scrollable. GtkViewPort is a bin container that provides the tools needed to allow its child to be scrolled. You can use the view port within a scrolled window to add scroll- bars that determine which part of the child should be shown. By themselves, view ports do not make a widget scrollable. GtkViewPort is simply a con- tainer that implements native scrollbar support, meaning that adding a widget to a view port doesn’t accomplish much unless the view port is then added to GtkScrolledWindow. Creating and using a GtkViewPort is rather easy. Listing 10-3 shows the code needed to add a table to a view port. Listing 10-3. Adding Scrollbars Using a GtkViewPort <?php // Create and set up a window. $window = new GtkWindow(); $window->connect_simple('destroy', array('gtk', 'main_quit')); // Add a table to the window. $table = new GtkTable(1, 1); // Add some stuff to the table that will make it large. $label = new GtkLabel('This is a rather long label. Hopefully ' . 'the table will scroll now.'); // Attach the label. $table->attach($label, 0, 1, 0, 1); // Create the view port. $viewPort = new GtkViewPort(); // Create the scrolled window. $sWindow = new GtkScrolledWindow(); // Add the table to the view port. $viewPort->add($table); // Add the view port to the scrolled window. $sWindow->add($viewPort); // Add the scrolled window to the main window. $window->add($sWindow); 6137ch10.qxd 3/14/06 2:16 PM Page 224 CHAPTER 10 ■ SCROLLING 225 Figure 10-5. A GtkTable inside a GtkViewPort // Show everything. $window->show_all(); gtk::main(); ?> ■Tip Adding scrolling capabilities to a widget doesn’t even have to be as complicated as Listing 10-3. The steps of creating a view port and adding it to a scrolled window can be consolidated. GtkScrolledWindow has a method named add_with_viewport. This method takes a widget and creates a view port for it auto- matically. The widget is then added to the view port, and the view port is added to the scrolled window. Only two lines are required to add scrollbars to the table. The first adds the table to the view port, and the second adds the view port to a scrolled window. The rest of the code in the exam- ple, aside from instantiating the view port and scrolled window, is set up for creating a table that will need to scroll. You determine if and where the scrollbars will appear in the view port in the same way as you do for the tree view, as described in the previous section. Figure 10-5 shows the result of running this code. ■Note GtkViewPort automatically adds a shadow to its child widget of type Gtk::SHADOW_IN. You can change this by calling set_shadow_type on the view port. You can also set a shadow for the GtkScrolledWindow in which the view port resides. This will cause a double border effect. Custom Scrolling Everything in PHP-GTK is designed to give flexibility to the developer. Scrolling is no excep- tion. You have total control over how a widget reacts when the user clicks a scrollbar. In fact, you don’t even need to use a scrolled window or a view port. When you use a scrolled window, the widget inside must listen to the scrolled window, but the way that a scrolled window controls a widget may be undesirable. For instance, scroll- ing the product tree in the previous examples moves the window by fractions of a row each time the user clicks the scroll arrows. Showing a fraction of a row isn’t very helpful to the user. It would be better if the widget scrolled by whole rows, so that the user sees the entire text of 6137ch10.qxd 3/14/06 2:16 PM Page 225 CHAPTER 10 ■ SCROLLING226 the first row. That is why GtkScrollbar widgets exist as their own classes and are not built into GtkScrolledWindow. Let’s take a look at what it takes to implement custom scrolling for the Crisscott_Tools_ ProductTree class. To provide scrolling for a widget requires a little bit of insight into how scrollbars actually work. Creating the Scrollbar GtkScrollbar is an abstract class that provides the basics for GtkHScrollbar and GtkVScrollbar. Scrollbars are only the visual component to scrolling. They work in conjunction with a GtkAdjustment. The adjustment manages the value and bounds of the scrollbar, while the scrollbar provides the visual representation of the value and communicates with the user. Every scrollbar has an adjustment that keeps track of the value and makes sure that the value stays within a certain range. The adjustment should be passed to the scrollbar on construction. Listing 10-4 shows how to create a vertical scrollbar. Instantiating the scrollbar is the easy part. It’s creating the adjustment that can be tricky. Listing 10-4. Creating a GtkVScrollbar <?php // Create an array consisting of the tree path. function createPathArray($model, $path, $iter, $pathArray) { $pathArray[0][] = $path; return false; } // Create a reasonably sized window to display the view. $window = new GtkWindow(); $window->set_size_request(150, 150); $window->connect_simple('destroy', array('gtk', 'main_quit')); // First create a model and view. require_once 'Crisscott/Tools/ProductTree.php'; $view = Crisscott_Tools_ProductTree::singleton(); $view->expand_all(); // Make the headers unclickable. $view->set_headers_clickable(false); $pathArray = array(); $view->get_model()->foreach('createPathArray', array(&$pathArray)); // Create the special vscrollbar. $lower = $value = 0; $upper = count($pathArray); $step = 1; $page = 6; $size = 1; 6137ch10.qxd 3/14/06 2:16 PM Page 226 CHAPTER 10 ■ SCROLLING 227 // Create the adjustment and add it to a scrollbar. $adj = new GtkAdjustment($value, $lower, $upper, $step, $page, $size); $vScroll = new GtkVScrollbar($adj) ?> An adjustment is nothing more than a collection of numbers that determine how the scrollbar will appear and function. Listing 10-4 shows how these values are collected from the product tree. An adjustment requires six numbers: • value: The value is simply set to 0 because the initial view should start at the beginning. The value of the adjustment is used to mark a tree path as selected. Look at the call to foreach on the view’s model. The callback builds an array of tree paths. Because foreach works in a depth-first manner, the array will be built with the first row shown as the first element and the last row shown as the last element. Changing the scrollbar’s value to 5 will scroll to the path defined by the array element with an index of 5. • lower: The lower bound is set to 0 because that is the lowest index in the array. • upper: The upper bound is set to the number of elements in the array. • step: The step size is the amount the value should change when the user clicks the arrows in the scrollbar. This is set to 1. • page: The page increment is the amount the value should change when the user clicks the empty space in the scrollbar. This is set to 6. This means that the selected row will be six rows up or down when the user pages the view. • size: The page size is set to 1 so that the scrollbar is allowed to move through the entire list. With these settings, the custom scrollbar is now ready to control the tree view. Creating the Signal Handlers To make the newly created scrollbar control the GtkTreeView, you need a few signal handlers. Listing 10-5 creates a signal handler for the scrollbar created in the previous listing. This signal handler connects the adjustment’s value-changed signal to the scrollView function. Listing 10-5. Creating the Signal Handler That Makes the View Scroll <?php // Function to scroll to and select a top level row. function scrollView($adj, $view, $pathArray) { // Create a path to a top level row. $path = $pathArray[$adj->get_value()]; // Set the cursor at that path. $view->set_cursor($path, $view->get_column(0), false); // Grab focus so that the cell is selected. $view->grab_focus(); } 6137ch10.qxd 3/14/06 2:16 PM Page 227 [...]... submenus $this->createButtons(); } protected function createButtons() { // Create a button to make new products, categories and // contributors $img = GtkImage::new_from_stock(Gtk::STOCK_NEW, Gtk::ICON_SIZE_SMALL_TOOLBAR); $new = new GtkMenuToolButton($img, 'New'); $newMenu = new GtkMenu(); // Create the menu items $product = new GtkMenuItem('Product'); $newMenu->append($product); $category = new GtkMenuItem('Category');... this a tear-off menu allows the user to quickly access the menu items for creating new products, categories, and contacts Listing 11-8 Creating a Tear-Off Menu . singleton product summary. require_once 'Crisscott/Tools/ProductSummary.php'; $productSummary = Crisscott_Tools_ProductSummary::singleton(); $productSummary->displaySummary($product); } public. Get a singleton instance of the product tree. require_once 'Crisscott/Tools/ProductTree.php'; $productTree = Crisscott_Tools_ProductTree::singleton(); 6137ch10.qxd 3/14/06 2:16 PM Page. them currently provides a graceful way to handle this data when it exceeds the boundaries of the tool. For instance, if the data contained within the product tree exceeds the space provided by the

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

TỪ KHÓA LIÊN QUAN