The TabBook Widget 1. Copyright Copyright 1995 Computer Generation, Inc. You may reproduce this document without charge provided the copyright and disclaimer notices appear. The software described in this document is copyrighted under separate terms. See the source code available at ftp://ftp.compgen.com/pub/widgets/TabBook.tar.Z The software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall Computer Generation, inc. nor the author be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software. The author welcomes comments and suggestions. Gary Aviv Computer Generation, Inc., gary@compgen.com 404-705-2811 2. Introduction TabBook is a Motif manager widget which is similar to Motif's own XmNotebook widget in appearance. It is significantly less complex and easier to use, though it has fewer features. It is intended for installations that lack Motif 2.x or just want basic notebook like functionality. TabBook sets up a series of "Tabs" along the top of a "page" area. Children of TabBook must be either push buttons or manager widgets (such as forms, bulletin boards, row-columns, etc. or a nested TabBook.) The push buttons are dressed with tab like borders and arranged horizontally. The child manager widgets are positioned in the page area so they overlap. There should be an equal number of manager and push button children. The page area is sized to fit the largest child manager.The overall TabBook widget then expands horizontally, if required, to fit all its tabs. There is one active page at a time. Its corresponding tab is drawn to appear "on top" and attached to the page. The user may press any tab to bring up its corresponding page and the associated manager widget. TabBook inherits behavior and resources from Core, Composite, Constraint, XmManager, and XmBulletinBoard. The class pointer is xcgTabBookWidgetClass. The class name is xcgTabBook. TabBook reliance on Motif is minor. It consists of inheriting behavior from XmManager, and XmBulletinBoard, setting resources in XmPushButton, knowing when a widget is an xmManagerWidgetClass subclass, and using XmGetColors. It should not be difficult adapting TabBook for use with other widget sets. 3. Version Information Initial. 4. Distribution Kit The source distribution kit contains the following files: TabBook.c TabBook.h TabBookP.h The TabBook widget source code TabBookTest.c A small demonstration program Imake an Imake file to build TabBookTest.c. TabBookTest.make A hand coded make file for several common OSs in case Imake fails. TabBook.html TabBook.txt Documentation in HTML, and plain text formats TabBook has been compiled successfully on NCR MPRAS, Digital OSF/Unix, Linux, and probably many others. To build the test program: xmkmf make 5. Resources TabBook adds the following resources to those it inherits. The resource class is obtained by replacing the N by a C in the resource name (eg: XtNactivePage is the name XtNactivePage is the class. The access types are C (resource may be set at create time), S (may be set using XtSetValues), or G (may be read using XtGetValues). XcgNactivePage Type = Integer, Default = 1, Access = CSG Sets the active page. Page numbering begins with 1. The tab of active page is redrawn to appear on top. When the resource autoManage is set, the corresponding manager widget for the page is managed and the previous active manager widget is unmanaged. If the widget is realized, the XcgNnewPageCallback callback is also called. See Section 10 for details. XcgNautoManage Type = Boolean, Default = True, Access = CSG Controls whether TabBook automatically manages the active page's manager widget when the user presses a tab. See Section 10 for details. XcgNnewPageCallback Type = Callback Default = None, Access = CSG The callback invoked when a tab button is pressed. See Section 7. 6. Constraint Resources TabBook has the following constraint resources that govern how manager children are positioned within their page. XcgNresizeChild Type = Integer, Default = XcgRESIZE_NONE, Access = CG defines whether a manager child is resized. possible values are: XcgRESIZE_NONE the child is not resized. XcgRESIZE_VERTICAL the child is resized to be the height of the page. Its width is not altered. XcgRESIZE_HORIZONTAL the child is resized to be the width of the page. Its height is not altered. XcgRESIZE_BOTH the child is resized to be the width and height of the page. This is the recommended setting for a TabBook that is a child of another TabBook. XcgNanchorChild Type = Integer, Default = XcgANCHOR_NORTHWEST, Access = CG Controls the placement of the child manager within the page. Possible values are: XcgANCHOR_CENTER The child is centered, horizontally and vertically. XcgANCHOR_EAST The child is right aligned and centered vertically. XcgANCHOR_NORTH The child is top aligned and centered horizontally. XcgANCHOR_NORTHEAST The child is top right aligned. XcgANCHOR_NORTHWEST The child is top left aligned. XcgANCHOR_SOUTH The child is bottom aligned and centered horizontally. XcgANCHOR_SOUTHEAST The child is bottom right aligned. XcgANCHOR_SOUTHWEST The child is bottom left aligned. XcgANCHOR_WEST The child is left aligned and centered vertically. 7. Callbacks The XcgNnewPageCallback callback is invoked when the user presses a tab button for a new page. If the user clicks the tab button of the current page, no action is taken at all. The callback is also called when the resource XcgNactivePage changes or optionally on a call of XcgTabBookSetActivePage. Finally, it is called when the TabBook widget is initially managed. In that case, the prev_active_page field is zero. The callback passes a pointer to the following structure: typedef struct _XcgTabBookCallbackData { XcgTabBookReasonType reason; /* reason for callback */ XEvent *event; /* button event, NULL if emulated */ int prev_active_page; /* 0 when initially called */ int active_page; /* new active page (1,2...) */ Widget button; /* the button widget which was pressed (emulated or actual*/ Boolean ret_veto; /* caller may set to True to stop page change */ int future1; void * future2; } XcgTabBookCallbackData; reason set to XcgNewPage event The XEvent of the button activate, or NULL if the callback was emulated. prev_active_page The page number that was previously active, or zero if this is the first time. active_page The page number of the newly active page. button The push button that was pressed, or NULL if emulated. ret_veto initialized to False. If the callback sets to True, then the button press is ignored. No change is made to a new active page. future Set to zero 8. Translations TabBook has no translations. 9. TabBook API TabBook contains the following functions that control the widget behavior. 9.1 XcgTabBookSetActivePage -- The active page is changed Function The active page is changed to the passed page number. Page numbers begin with 1. If this results in a new active page, the effect is as if the user pressed the corresponding tab button. It is also equivalent to setting the resource, XcgNactivePage. However, the NewPage callback that would normally be called under these circumstances can be optionally suppressed. See Section 10 for details. C-call Boolean XcgTabBookSetActivePage(Widget w, int page, int option ) Input w TabBook widget page the page number to activate. option bitmapped XcgTabBook_OPT_NO_CB - don't call NewPage callback Output Nothing Return True - page has been changed False - non-existent page number 9.2 XcgTabBookGetActivePage -- The active page is returned Function C-call int XcgTabBookGetActivePage(Widget w) Input w TabBook widget Output Nothing Return The current active page number (1,2,...) A zero means the widget has not been managed at least once. 10. Widget Logic When the resource autoManage is set, TabBook handles all details of page management. Each child manager widget is forced to be un-managed except for the one corresponding to the active page. When the user presses a tab pushbutton, the old manager is un-managed and the new active page's manager widget is managed so it appears. The order of insertion of child widgets into TabBook determines the correspondence of pushbutton tabs to manager widgets. You may insert all pushbuttons then all manager widgets or you may interleave them. The first pushbutton inserted corresponds to the first manager widget inserted and these constitute page 1. In order to monitor when the user changes pages, You may add a callback to each tab pushbutton or you can use the XcgNnewPageCallback callback. The latter technique allows you to veto the change in page if, for example, you detect an error.