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

Linux programming unleash phần 7 potx

84 292 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

Thông tin cơ bản

Định dạng
Số trang 84
Dung lượng 521,65 KB

Nội dung

sprintf(sp1, “%s”, w->url.data); len = strlen(sp1); while (1) { sp2 = strstr(sp1, “\n”); if (sp2 != NULL) { // keep going *sp2 = ‘\0’; sp3 = clean_text(sp1); XDrawString(XtDisplay(w), XtWindow(w), w->url.gc, 10, y, sp3, strlen(sp3)); y += 12; sp1 = sp2 + 1; } else { // time to stop sp3 = clean_text(sp1); XDrawString(XtDisplay(w), XtWindow(w), w->url.gc, 10, y, sp3, strlen(sp3)); break; } // check to avoid running past data: if (sp1 >= &(buf[0]) + len) break; } } The implementation of the URLWidget is actually very simple. Most of the work lies in following the strict X toolkit protocol for writing widgets. In principle, the URLWidget can be used in any X application, including applications using Motif widgets. Testing the URLWidget If you have not already done so, you should compile and run the test.c program by changing the directory to src/X/URLWidget and typing: make ./test You must type ./test instead of test to avoid running the system utility “test” that checks file types. This test program is simple. Using a widget should be much easier than writing the code to implement it. We start by including both the standard X11 header files and the public URLWidget header file: #include <X11/StringDefs.h> #include <X11/Intrinsic.h> #include “URL.h” The function main defines two widgets (top_level and url)and creates the top_level widget: Widget top_level, url; top_level = XtInitialize(argv[0], “urltest”, NULL, 0, &argc, argv); Programming the User Interface P ART IV 506 3472316072 CH29 7/26/99 1:35 PM Page 506 We need to set the width, height, and URLResource resources for the url widget before creating the url widget: Arg args[3]; XtSetArg(args[0], XtNwidth, 520); XtSetArg(args[1], XtNheight, 580); XtSetArg(args[2], XtNURLResource, “www.knowledgebooks.com”); url = XtCreateManagedWidget(“url”, urlWidgetClass, top_level, args, 3); Finally, we realize the Top-Level widget and handle X events: XtRealizeWidget(top_level); XtMainLoop(); Figure 29.8 shows a the test.c program running. Using Athena and Motif Widgets C HAPTER 29 507 29 USING ATHENA AND MOTIF WIDGETS FIGURE 29.8 Testing URLWidget. Using Both Athena and Motif in C++ Programs When I first started programming in C++ in the late 1980s, I also learned X Windows programming at roughly the same time. The bad news back then was that the X toolkit and the Athena widgets were not very “C++ friendly,” so I spent a great deal of time combining Widgets with C++ programs. Well, the good news now is that the X11 3472316072 CH29 7/26/99 1:35 PM Page 507 libraries, header files, and so on work effortlessly with the C++ language. If you look in the directory src/X/list_C++, you will see two source files: athena.cpp—this is the src/X/Athena/list.c example renamed motif.cpp—this is the src/X/Motif/list.c example renamed Except for one compiler warning about printf, these examples compile with the C++ compiler and run fine. Try this yourself; change the directory to src/X/list_C++ and type: make athena motif Because a C++ compiler provides better compile-time error checking than a C compiler, I recommend using C++ instead of C even if you are not using the object-oriented fea- tures of C++ (for example, no class definitions). Using a C++ Class Library for Athena Widgets In this section, we will learn about a very simple C++ library that encapsulates the fol- lowing Athena widgets: Widget Description Paned Wrapped in the C++ class PanedWindow (which also generates a Top-Level Application widget). Label Wrapped in the C++ class Label. Command Button Wrapped in the C++ class Button. AsciiText Wrapped in the C++ class Text. As some motivation for this exercise, I will first show a simple test program that contains absolutely no (obvious) X Windows code. The example program, test_it.cpp, is locat- ed in the directory src/X/C++ and is listed below. iostream.h defines standard C++ I/O. The include files PanedWindow.h, Label.h, Button.h, and Text.h define our C++ classes that wrap the corresponding Athena widgets: #include <iostream.h> #include “PaneWindow.hxx” Programming the User Interface P ART IV 508 3472316072 CH29 7/26/99 1:35 PM Page 508 #include “Label.hxx” #include “Button.hxx” #include “Text.hxx” We will create one each of these C++ objects. The button will have a Callback function that prints the content of the text object. We make the Text object global so that the button_cb Callback function can access it: Text *text; The button_cb Callback function uses the public getText method of the Text class to print whatever text has been typed into the text object: void button_cb() { cout << “Text is:\n” << text->getText() << “\n”; } The function main is very simple. We construct one instance each of our wrapper classes, use the PaneWindow class’s public addComponent method to add the Label, Button and Text objects to the paned window object, and then call the PaneWindow class’s public run method to handle events. Note that the constructor for the Button class takes a C func- tion as the second argument; this function will be called whenever the button is clicked with the mouse pointer. void main() { PaneWindow pw; Label label(“this is a test”); Button button(“Get text”, button_cb); text = new Text(300, 120); pw.addComponent(&label); pw.addComponent(&button); pw.addComponent(text); pw.run(); } Figure 29.9 shows the example program test_it.cpp running. Using Athena and Motif Widgets C HAPTER 29 509 29 USING ATHENA AND MOTIF WIDGETS F IGURE 29.9 Testing the C++ class library for wrapping Athena widgets. 3472316072 CH29 7/26/99 1:35 PM Page 509 The PaneWindow class does most of the work in this class library. This class is responsi- ble for the behavior of adding sub-components and handling X events. The classes Label, Button, and Text are all derived from a base class Component that has one impor- tant virtual method, setup. I designed the class library in this way so that the PaneWindow class can simply keep an array of pointers to instances of classes derived from class Component. The public run method of class PanedWindow creates all of the contained widgets by calling the method setup for each component that has been added to a paned window object. The method run then internally handles all X events. The implementation of this class library is simple, and you should find it easy to add to this library other widgets for your applications. The only complication involves handling C language Callback functions. We will soon see how this is done in the implementation of the Button class. The Component Class The Component class is the base class for the Label, Button, and Text classes. If you want to wrap additional widgets in a C++ class and add them to this library, your new classes should also be derived from the Component class. The header file for this class is fairly simple. As is typical of header files, the entire contents of the Component.hxx file is “wrapped” in a #ifndef statement: #ifndef Component__hxx #define Component__hxx This #ifdef assures us that this file will not be included twice in any compiled code. We also need the standard X toolkit include file for the definition of the type of Top-Level Application widget: #include <X11/Intrinsic.h> The class definition is simple. The constructor for this class does almost nothing, and the virtual method setup must always be overridden in derived classes because it is a “pure virtual” function—the method is set to zero. The public getWidget method simply returns the values of the private variable my_widget. class Component { public: Component(); virtual void setup(Widget parent) = 0; Widget getWidget() { return my_widget; } protected: Widget my_widget; }; Programming the User Interface P ART IV 510 3472316072 CH29 7/26/99 1:35 PM Page 510 The implementation of the Component class in the file Component.cxx is also simple: // Component.cpp // #include <X11/Intrinsic.h> #include “Component.hxx” Component::Component() { my_widget = (Widget)NULL; } The class constructor for Component sets the private variable my_widget to a NULL value, which is not strictly necessary. The PanedWindow Class It was important to see the definition of the Component class before the PaneWindow class because a pane window object maintains an array of pointers to objects derived from the Component class. The header file for this class is PaneWindow.h, where we need four include file: #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Xaw/Paned.h> #include “Component.hxx” The first three include files are required for X Windows definitions- and the fourth is the header file for the Component class. The PaneWindow class has three public methods: Method Description PaneWindow Class constructor. addComponent(Component * comp) Adds other components to the paned window. run() Creates all the contained components and handles events. The private data for the class PaneWindow contains X Windows-specific data that users of this class library can ignore. There is also private data to store up to 10 pointers to objects belonging to any class derived from the Component class. class PaneWindow { public: PaneWindow(); Using Athena and Motif Widgets C HAPTER 29 511 29 USING ATHENA AND MOTIF WIDGETS 3472316072 CH29 7/26/99 1:35 PM Page 511 void addComponent(Component * comp); void run(); private: Widget top_level; Widget pane; Component * components[10]; int num_components; XtAppContext application_context; }; The implementation of the PaneWindow class, in the file PaneWindow.cxx, requires three include files; the first two are X-related and the third is the class definition header file: #include <X11/Intrinsic.h> #include <X11/Xaw/Paned.h> #include “PaneWindow.hxx” The following X resources are defined for the components that might be added to a paned window: static String app_resources[] = { “*Text*editType: edit”, “*Text*autoFill: on”, “*Text*scrollVertical: whenNeeded”, “*Text*scrollHorizontal: whenNeeded”, “*Text*preferredPaneSize: 300”, NULL, }; If you create new subclasses of Component to encapsulate other types of widgets, you might want to add default resources for those widget types to the app_resources array. The PaneWindow class constructor creates a Top-Level Application widget and an Athena Paned widget: PaneWindow::PaneWindow() { int argc = 0; char ** argv = NULL; top_level = XtAppInitialize(&application_context, “top_level”, NULL, 0, &argc, argv, app_resources, NULL, 0); num_components = 0; pane = XtVaCreateManagedWidget(“paned”, panedWidgetClass, top_level, NULL); } Programming the User Interface P ART IV 512 3472316072 CH29 7/26/99 1:35 PM Page 512 The method run creates components that have been added to the PaneWindow object and then handles X events. The class variable num_components is a counter for the number of components added to this object using the addComponent method: void PaneWindow::run() { // Start by adding all registered components: for (int i=0; i<num_components; i++) { components[i]->setup(pane); XtManageChild(components[i]->getWidget()); } XtRealizeWidget(top_level); XtAppMainLoop(application_context); } The method addComponent is used to add components to a PaneWindow object: void PaneWindow::addComponent(Component * comp) { components[num_components++] = comp; } The Label Class The Label class is derived from the class Component. The class header file Label.hxx requires only one header file, which is the definition file for its base class: #include “Component.hxx” The class definition is simple. The constructor takes three arguments and the class has private data so that the setup method can properly create the label when it is called from the PaneWindow object’s run method: class Label : public Component { public: Label(char * label = “test label”, int width=100, int height=20); void setup(Widget parent); private: char * my_label; int my_width; int my_height; }; The implementation for this class is also straight forward. The file Label.cxx requires four include files, three of which are X Windows-specific and one defines the Label class: #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Xaw/Label.h> #include “Label.hxx” Using Athena and Motif Widgets C HAPTER 29 513 29 USING ATHENA AND MOTIF WIDGETS 3472316072 CH29 7/26/99 1:35 PM Page 513 The class constructor simply stores its three arguments for later use by the setup method: Label::Label(char *label, int width, int height) { my_label = label; my_width = width; my_height = height; } The method setup is called by the method run of a PaneWindow object; setup is called with the Athena Paned widget created in the constructor of the PaneWindow object. All component widgets added will therefore have the Athena Paned widget as a common parent: void Label::setup(Widget parent) { Arg args[2]; XtSetArg(args[0], XtNwidth, my_width); XtSetArg(args[1], XtNheight, my_height); my_widget = XtCreateManagedWidget(my_label, labelWidgetClass, parent, args, 2); } The Button Class The Button class is much more interesting than the Label class because it has to handle Callback functions. The header file Button.hxx needs two include files: one for the Athena Command widget and one for the definition of the Component C++ class: #include <X11/Xaw/Command.h> #include “Component.hxx” The header file defines the type of the Callback function as a function pointer to a func- tion with no arguments and that has no return value: typedef void (*button_callback)(void); The class definition is: class Button : public Component { public: Button(char * label = “test label”, button_callback cb = 0, int width=130, int height=30); void setup(Widget parent); button_callback my_cb; private: char * my_label; int my_width; int my_height; }; Programming the User Interface P ART IV 514 3472316072 CH29 7/26/99 1:35 PM Page 514 The class implementation file Button.cxx requires four include files: three for X Windows and one that defines the C++ Button class: #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Xaw/Command.h> #include “Button.hxx” All instances of the Button class use one static C Callback function. This function is passed a pointer to a Button object, so that the button object’s Callback function can be called. This allows multiple instances of the Button class with different Callback func- tions to function correctly in a single program: static void callback(Widget w, caddr_t data1, caddr_t data2) { Button * b = (Button *)data1; if (b != 0) b->my_cb(); } The class constructor stores the values of its four arguments in private data: Button::Button(char *label, button_callback cb, int width, int height) { my_label = label; my_width = width; my_height = height; my_cb = cb; } The setup method creates the button’s widget and sets up the Callback function that is shared by all instances of this class: void Button::setup(Widget parent) { Arg args[2]; XtSetArg(args[0], XtNwidth, my_width); XtSetArg(args[1], XtNheight, my_height); my_widget = XtCreateManagedWidget(my_label, commandWidgetClass, parent, args, 2); XtAddCallback(getWidget(), XtNcallback, callback, (XtPointer) this); } The Text Class The Text class wraps (or encapsulates) the Athena AsciiText Top-Level Application widget. The class implementation file Text.hxx requires two include files: one for the standard X Windows definitions and one for the C++ Component class definition: #include <X11/Intrinsic.h> #include “Component.hxx” Using Athena and Motif Widgets C HAPTER 29 515 29 USING ATHENA AND MOTIF WIDGETS 3472316072 CH29 7/26/99 1:35 PM Page 515 [...]... writing both Athena and Motif based programs 3 472 316 072 CH29 7/ 26/99 1:35 PM Page 518 518 CHAPTER 30 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 519 GUI Programming Using GTK by Mark Watson IN THIS CHAPTER • Introduction to GTK 521 • A GTK Program for Displaying XML Files 528 • A GUI Program using the Notebook Widget 5 37 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 520 520 Programming the User Interface PART IV The Gimp... spent because you not only become familiar with the look and feel of the GTK widgets, you can also look at the short source-code files for each sample program 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 5 27 GUI Programming Using GTK CHAPTER 30 5 27 FIGURE 30.1 Four sample programs included with the standard GTK distribution GTK Container Widgets Although there are many types of container widgets in GTK (again,... application reads XML data from stdin To compile and execute this example program, change the directory to src/GTK and type the following: make cat test.xml | XMLviewer 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 5 37 GUI Programming Using GTK CHAPTER 30 5 37 Figure 30.2 shows two copies of the XMLviewer sample program running side-by-side On the left side of the figure, the tree is collapsed The right side of Figure... type, and a flag to indicate if word-wrap is allowed, as shown in the following: 30 GUI PROGRAMMING USING GTK struct _GtkLabel { GtkMisc misc; gchar *label; GdkWChar *label_wc; gchar *pattern; GtkLabelWord *words; guint max_width : 16; guint jtype : 2; gboolean wrap; }; 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 522 522 Programming the User Interface PART IV The GtkMisc structure definition starts with a GtkWidget... gtk_widget_show(button); gtk_widget_show(window); // Handle events: gtk_main(); } GUI PROGRAMMING USING GTK The main function creates two GtkWidget object pointers: window and button These widget pointers are used to reference a top-level window and a button widget In the call 30 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 526 526 Programming the User Interface PART IV to gtk_signal_connect, we use macros to coerce... XtSetArg(args[1], XtNheight, my_height); my_widget = XtVaCreateManagedWidget(“text”, asciiTextWidgetClass, parent,XtNtype,XawAsciiString, XtNstring, “ “, args, 2, NULL); } 3 472 316 072 CH29 7/ 26/99 1:35 PM Page 5 17 Using Athena and Motif Widgets CHAPTER 29 5 17 The getText method returns the text that the user has typed into the Athena AsciiText Top-Level Application widget The X toolkit function XtVaGetValues is used... adjusted by the user Contains a row of buttons used for selecting program options GUI PROGRAMMING USING GTK If you download and install the current version of GTK from www.gtk.org, you can find sample programs that use all types of container widgets in the examples directory 30 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 528 528 Programming the User Interface PART IV A GTK Program for Displaying XML Files We develop... Clark, whose Web site is http://www.jclark.com/xml/expat.html 30 GUI PROGRAMMING USING GTK You can find this parser on the CD-ROM in the src/GTK/expat directory We will use this parser in the next section to write a GTK program to display both the tree structure and content of XML documents 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 530 530 Programming the User Interface PART IV The elements.c file in the... Watson” • startElement—Called • endElement—Called with the name of a tag when the tag is first processed with the name of the tag after handleElementData is called 30 GUI PROGRAMMING USING GTK • 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 532 532 Programming the User Interface PART IV The function handleElementData is called by the expat parser to process data inside of tags The function signature is as follows:... node at a time: gtk_tree_set_selection_mode(GTK_TREE(tree), GTK_SELECTION_SINGLE); GUI PROGRAMMING USING GTK To enable multiple selection, the GTK constant GTK_SELECTION_SINGLE that is defined in the gtkenums.h file can be replaced by the GTK_SELECTION_MULTIPLE constant 30 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 536 536 Programming the User Interface PART IV The XML parser, which is referenced with the variable . programs. Using Athena and Motif Widgets C HAPTER 29 5 17 29 USING ATHENA AND MOTIF WIDGETS 3 472 316 072 CH29 7/ 26/99 1:35 PM Page 5 17 518 3 472 316 072 CH29 7/ 26/99 1:35 PM Page 518 IN THIS CHAPTER • Introduction. Widget 5 37 30 CHAPTER GUI Programming Using GTK by Mark Watson 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 519 The Gimp Tool Kit (GTK) is widely used for writing X Windows applications on Linux and. max_width : 16; guint jtype : 2; gboolean wrap; }; GUI Programming Using GTK C HAPTER 30 521 30 GUI PROGRAMMING USING GTK 3 572 316 072 CH30 7/ 26/99 2:11 PM Page 521 The GtkMisc structure definition

Ngày đăng: 12/08/2014, 21:20

TỪ KHÓA LIÊN QUAN