\input texinfo @c -*-texinfo-*- @c %**start of header @settitle User's Guide to the GNUstep GUI Library @setfilename gstep-gui.info @c %**end of header @defcodeindex cl @defcodeindex pr @ignore I'm using cindex for concepts, findex for methods, functions and macros, prindex for protocols, and clindex for classes. @end ignore @ifinfo @format START-INFO-DIR-ENTRY * gstep-gui:: The GNUstep GUI Library END-INFO-DIR-ENTRY @end format @end ifinfo @c set the vars GNUSTEP-GUI-VERSION and GCC-VERSION @include version.texi @ifinfo This file documents the features and implementation of The GNUstep GUI Library. Copyright (C) 1999 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the section entitled ``GNU Library General Public License'' is included exactly as in the original, and provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that the section entitled ``GNU Library General Public License'' and this permission notice may be included in translations approved by the Free Software Foundation instead of in the original English. @end ifinfo @iftex @finalout @c @smallbook @c @cropmarks @end iftex @setchapternewpage odd @titlepage @title User's Guide to the @title GNUstep GUI Library @sp 3 @subtitle Version @value{GNUSTEP-GUI-VERSION} @author A. Fedor (fedor@@gnu.org), N. Pero (n.pero@@mi.flashnet.it) @page @vskip 0pt plus 1filll Copyright @copyright{} 1999 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the section entitled ``GNU Library General Public License'' is included exactly as in the original, and provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that the section entitled ``GNU Library General Public License'' may be included in a translation approved by the author instead of in the original English. @end titlepage @ifinfo @node Top, Overview, (dir), (dir) @top gstep-gui @end ifinfo This manual documents some configuration and installation issues with the GNUstep GUI Library and also differences between the GUI Library and libraries that implement the OpenStep AppKit specification and the MacOS-X AppKit implementation. @menu * Overview:: * Configuration:: * Classes:: * Tools:: * Implementation:: * Setup:: * Contributing:: * Concept Index:: @end menu @node Overview, Configuration, Top, Top @chapter Overview The GNUstep GUI Library is a library of objects useful for writing graphical applications. For example, it includes classes for drawing and manipulating graphics objects on the screen: windows, menus, buttons, sliders, text fields, and events. There are also many peripheral classes that offer operating-system-independent interfaces to images, cursors, colors, fonts, pasteboards, printing. There are also workspace support classes such as data links, open/save panels, context-dependent help, spell checking. It provides functionality that aims to implement the @samp{AppKit} portion of the OpenStep standard. However the implementation has been written to take advantage of GNUstep enhancements wherever possible. The GNUstep GUI Library is divided into a front and back-end. The front-end contains the majority of implementation, but leaves out the low-level drawing and event code. Different back-ends will make GNUstep available on various platforms. The default GNU back-end currently runs on top of the X Window System and uses only Xlib calls for graphics. Another backend uses a Display Postscript Server for graphics. Much work will be saved by this clean separation between front and back-end, because it allows different platforms to share the large amount of front-end code. Documentation for how the individual backends work is coverered in a separate document. @node Configuration, Classes, Overview, Top @chapter Configuration There is no special configuration to be done for the GUI library. It is best to configure, compile, and install the gstep-gui library along with all the other GNUstep libraries. For this, you should get the gstep-core package and follow the installation instructions for that. If you are compiling this library separately, you must have already installed the GNUstep Makefile Pacakge and the GNUstep Base Library. @node Classes, Tools, Configuration, Top @chapter Special Features of GUI Classes. @menu * NSApplication:: * NSBrowserCell:: * NSSavePanel:: * GSHbox:: * GSTable:: * GSVbox:: @end menu @node NSApplication, NSBrowserCell, Classes, Classes @section NSApplication @menu * Standard Info Panel:: @end menu @node Standard Info Panel, , NSApplication, NSApplication @subsection Standard Info Panel GNUstep NSApplication provides the following two methods to easily create a standard Info Panel for your application: @noindent - (void) @b{orderFrontStandardInfoPanel:} (id)@t{sender} Invokes @code{orderFrontStandardInfoPanelWithOptions:} with a @code{nil} dictionary. You may use this method as action of a menu item, even if it is generally preferred to use the full method so that you can fill in all the information to show in the Info Panel. @noindent - (void) @b{orderFrontStandardInfoPanelWithOptions:} (NSDictionary *)@t{dictionary} Orders front the standard info panel for the application, taking the needed information from the @t{dictionary} argument. There is a single standard info panel per application; it is created the first time that this method is invoked, and then reused in all subsequent calls. The application standard info panel is immutable and can not be changed after creation. Useful keys for the @t{dictionary} are: @code{ApplicationName}: A string with the name of the application (eg, @code{@@"Gorm"}). If not available, the @file{Info-gnustep.plist} file is searched for the value of @code{ApplicationName}; if this fails, the @file{Info-gnustep.plist} file is searched for the value of @code{NSHumanReadableShortName}; if this also fails, the string returned by @code{[[NSProcessInfo processInfo] processName]} is used. @code{ApplicationDescription}: A string with a very short description of the application (eg, @code{@@"GNUstep Graphics Objects Relationship Modeller"}). If not available, @file{Info-gnustep.plist} is searched for that key; if this fails, no application description is shown. @code{ApplicationIcon}: An image to be shown near the title. If not available, @file{Info-gnustep.plist} is looked for @code{ApplicationIcon}; if this fails, @code{[NSApp applicationIconImage]} is used instead. Since this is what you usually want, you usually do not need to set the @code{ApplicationIcon} key/value in the @code{dictionary}. @code{ApplicationRelease}: A string with the name of the application, release included (eg, @code{@@"Gorm 0.1"}). If not available, the value for @code{ApplicationVersion} is used instead. If this fails, @file{Info-gnustep.plist} is looked for @code{ApplicationRelease} or (failing this) for @code{NSAppVersion}. If all fails, @code{"Unknown"} is used. @code{FullVersionID}: A string with the full version of the application (eg, @code{@@"0.1.2b"} or @code{@@"snap011100"}). If not available, @code{Version} is used instead. If this fails, @file{Info-gnustep.plist} is looked for @code{NSBuildVersion}. If all fails, no full version is shown. @code{Authors}: An array of strings, each one with the name of an author (eg, @code{[NSArray arrayWithObject: @@"Nicola Pero "]}). If not found, @file{Info-gnustep.plist} is looked for @code{Authors}, if this fails, @code{@@"Unknown"} is displayed. @code{URL}: [This field is still under work, so it might be changed] A string with an URL (eg, @code{@@"See http://www.gnustep.org"}). @code{Copyright}: A string with copyright owners (eg, @code{@@"Copyright (C) 2000 The Free Software Foundation, Inc."}). Support for multiple line strings is planned but not yet available. If not found, @file{Info-gnustep.plist} is searched for @code{Copyright} and then (failing this) for @code{NSHumanReadableCopyright}. If all fails, @code{@@"Copyright Information Not Available"} is used. @code{CopyrightDescription}: A string describing the kind of copyright (eg, @code{@@"Released under the GNU General Public License 2.0"}). If not available, @file{Info-gnustep.plist} is looked for @code{CopyrightDescription}. If this fails, no copyright description is shown. For compatibility reasons only, the following MacOSX API is also available: @noindent - (void) @b{orderFrontStandardAboutPanel:} (id)@t{sender} @noindent - (void) @b{orderFrontStandardAboutPanelWithOptions:} (NSDictionary *)@t{dictionary} These methods do the same as the ones above, but are deprecated. Please note that you are free to implement your own info panel for your app without breaking the GNUstep User Interface; the standard one is available only as a facility -- it's not at all compulsory to use the standard one -- you are encouraged to create your own if you like. What is important instead is that you make your info panel available from the @t{Info...} item in the @t{Info} menu. @node NSBrowserCell, NSSavePanel, NSApplication, Classes @section NSBrowserCell @menu * GSBrowserCellFontify:: @end menu @node GSBrowserCellFontify, , NSBrowserCell, NSBrowserCell @subsection GSBrowserCellFontify GNUstep NSBrowserCell has an experimental feature (disabled by default), which you may turn on by setting the @code{GSBrowserCellFontify} user default to @code{YES}. To turn it on, issue the command: @smallexample defaults write NSGlobalDomain GSBrowserCellFontify YES @end smallexample To turn it off: @smallexample defaults delete NSGlobalDomain GSBrowserCellFontify @end smallexample When the feature is on, NSBrowserCell draws non leaf cells in bold system font (as opposed to the leaf cells, which are drawn in (non bold) system font). For example, when the feature is on, in a SavePanel (or OpenPanel), directory entries are drawn in bold, while simple files are drawn in non bold. @node NSSavePanel, GSHbox, NSBrowserCell, Classes @section NSSavePanel @menu * GSSavePanelShowProgress:: @end menu @node GSSavePanelShowProgress, , NSSavePanel, NSSavePanel @subsection GSSavePanelShowProgress GNUstep NSSavePanel has an experimental feature (disabled by default), which you may turn on by setting the @code{GSSavePanelShowProgress} user default to @code{YES} (see the previous section on how to do it). When the feature is on, the save panel and its subclasses (such as the open panel) displays "Reading Directory ***.." (progressively adding dots) in the window titlebar while reading very big directories (more than 100 entries). This is meant to make things friendlier for slow computers (to me, it definitely does). If your computer is fast, you'd better leave the feature disabled. The feature is experimental in all senses: it could be unstable. @node GSHbox, GSTable, NSSavePanel, Classes @section GSHbox Reference @menu * GSHbox Class:: * GSHbox Overview:: * GSHbox Method Description:: @end menu @node GSHbox Class, GSHbox Overview, GSHbox, GSHbox @subsection @code{GSHbox} Class @display Inherits from: @code{GSTable: NSView: NSResponder: NSObject}@* Conforms to: @code{NSCoding} (from @code{NSResponder})@* @ @ @ @ @ @ @ @code{NSObject} (from @code{NSObject})@* Declared in: @file{AppKit/GSHbox.h} @end display @code{GSHbox} is a GNUstep GUI extension to the OpenStep specification. @node GSHbox Overview, GSHbox Method Description, GSHbox Class, GSHbox @subsection Overview of the @code{GSHbox} Class @code{GSHbox} is a subclass of @code{GSTable} meant to provide an extremely simplified API for managing rows of views. The only real difference between a @code{GSHbox} and a @code{GSTable} with 1 row is that @code{GSHbox} has a much simpler, easier and less powerful API. This difference makes programming with @code{GSHbox} (and @code{GSVbox}) much faster than dealing directly with the underlying @code{GSTable}. If you use @code{GSHbox}, it is to take advantage of the simplified API. You shouldn't use @code{GSTable} methods with @code{GSHbox} (exception: methods explicitly listed in this documentation), because @code{GSHbox} is supposed to manage those methods for you. If you need the power of the full @code{GSTable} API, you should simply be using @code{GSTable} and not @code{GSHbox}. A @code{GSHbox} is an invisible view (a logical device) which can contain some views. The @code{GSHbox} controls the position and sizes of these views so that they are lined up in a row. To initialize a @code{GSHbox}, you should always use @code{-init} method. Don't use @code{GSTable} methods. The correct way to start using a new @code{GSHbox} is simply: @smallexample hbox = [GSHbox new]; @end smallexample (well, of course, autoreleasing it if necessary). You add a view to a @code{GSHbox} using the method @code{-addView:} and its variants. The views you add to a @code{GSHbox} are placed by the @code{GSHbox} in its subview hierarchy, and moved (and/or resized in the vertical direction) so that they are positioned one after the other, from left to right, in a row. Before adding views to a box, you should resize them to the least comfortable size you want them to have. The @code{GSHbox} considers this size as the minimum size your view should ever have, and never resizes your view below this size. The initial size of the @code{GSHbox} is zero; each time you add a view in the @code{GSHbox}, the @code{GSHbox} resizes itself to fit the new contents. Usually, you simply add objects to the @code{GSHbox}, and let it compute its size (this is the minimum size); you may get this resulting size by @smallexample size = [yourHBox size]; @end smallexample for example, if the @code{GSHbox} is to be used as the content view of a window, you may create the window exactly with this size. You should never force a @code{GSHbox} in a size different from the one it has automatically computed. It sounds quite pointless anyway. The only correct (and meaningful) way to resize a @code{GSHbox} is through @code{-resizeWithOldSuperviewSize:} messages (in the view hierarchy). In other words, after you place your box in the view hierarchy, then you may resize the superview and (if the superview has autoresizing of subviews enabled) your box is resized automatically accordingly. By default, there is no space between the added views. By using the method @code{-addView:withMinXMargin:} you may tell the @code{GSHbox} to insert some space (a @dfn{margin}) between the view you are adding and the previous one (the one at its left). @c Don't talk about setDefaultMinXMargin: here. If what you want is space around the @code{GSHbox}, and not between views in the @code{GSHbox}, you don't want a margin but a @dfn{border}; you should then use @code{-setBorder:}, which will add an equal amount of space on all the sides of the box. You can also set a different border on each side (see @code{-setMinXBorder:} and similar methods). A useful feature of @code{GSHbox} is that it supports @dfn{separators}. This facility is not directly available in @code{GSTable} (to add separators to a @code{GSTable} you need to create and handle them yourself). A @code{GSHbox} separator is a vertical groove line, used to mark the separation between different elements of a box. To add a separator, simply invoke the method @code{-addSeparator}. The separator is put at the right of the last added view. To use @code{GSHbox} proficiently, it is crucial to set correctly the autoresizing mask of each view before adding it to the @code{GSHbox}. The @code{GSHbox} treats each view and its margins as a whole (see the @code{GSTable} class description for more information). When the @code{GSHbox} is resized in the vertical direction (as a consequence of user intervertion, for example), what happens is: @itemize @bullet @item if the new height is less than the minimum height of the @code{GSHbox} (computed as the maximum of the minimum height of the added views), it simply resizes all the added views to this minimum height; part of them are clipped then. @item if the new height is greater than the @code{GSHbox}'s minimum height, the @code{GSHbox} resizes all the added views to the new height. This is done through the standard superview-subview resizing mechanism, so that, by setting the @code{autoresizingMask} of each view that you add, you are able to control exactly how the resizing effects each view and its margins. @end itemize When the @code{GSHbox} is resized in the horizontal direction, its behaviour is as follows: @itemize @bullet @item If the new width is less than the minimum width, all the added views are sized to minimum width; part of them is clipped then. @item If the new width is greater than the minimum width, some of the views are resized. You may decide which views you want to be resized and which not; to disable resizing of a certain view in the horizontal direction, you should specify a @code{NO} value to the option @code{enablingXResizing} when you add the view to the box. Views with X Resizing Not Enabled are always kept in their minimum width (the original one), and never resized. If nothing is specified, a default of @code{YES} for @code{enablingXResizing} is understood. So, when the new width is greater than the minimum width, the excess width is equally divided between the view with X Resizing Enabled. The actual resizing is done through the usual superview-subview resizing mechanism, so that again you may influence the way the resizing affects each view by setting the autoresizing mask of each view. @end itemize @node GSHbox Method Description, , GSHbox Overview, GSHbox @subsection @code{GSHbox} Method Description @menu * Initializing:: * Setting Box Borders:: * Adding a View:: * Adding a Separator:: * Setting Margins:: * Getting the Minimum Size:: * Resizing the Box:: * Getting the Number of Views:: @end menu @node Initializing, Setting Box Borders, GSHbox Method Description, GSHbox Method Description @subsubsection Initializing @noindent -(id) @b{init} Initialize the @code{GSHbox}. This is the only allowed initialization method for @code{GSHbox}. @node Setting Box Borders, Adding a View, Initializing, GSHbox Method Description @subsubsection Setting the Box Borders @noindent -(void) @b{setBorder:} (float)@t{aBorder} See the @code{GSTable} class description. @noindent -(void) @b{setXBorder:} (float)@t{aBorder} See the @code{GSTable} class description. @noindent -(void) @b{setYBorder:} (float)@t{aBorder} See the @code{GSTable} class description. @noindent -(void) @b{setMinXBorder:} (float)@t{aBorder} See the @code{GSTable} class description. @noindent -(void) @b{setMaxXBorder:} (float)@t{aBorder} See the @code{GSTable} class description. @noindent -(void) @b{setMinYBorder:} (float)@t{aBorder} See the @code{GSTable} class description. @noindent -(void) @b{setMaxYBorder:} (float)@t{aBorder} See the @code{GSTable} class description. @node Adding a View, Adding a Separator, Setting Box Borders, GSHbox Method Description @subsubsection Adding a View @noindent -(void) @b{addView:} (NSView *)@t{aView} Add a view to the box, enabling X resizing, and with the default MinXMargin. @noindent -(void) @b{addView:} (NSView *)@t{aView}@* @ @ @ @ @b{enablingXResizing:} (BOOL)@t{aFlag} Add a view to the box with the default MinXMargin, enabling X resizing only if @code{aFlag} is @code{YES}, @noindent -(void) @b{addView:} (NSView *)@t{aView}@* @ @ @ @ @b{withMinXMargin:} (float)@t{aMargin} Add a view to the box with @code{aMargin} MinXMargin, and enabing X resizing. @noindent -(void) @b{addView:} (NSView *)@t{aView}@* @ @ @ @ @b{enablingXResizing:} (BOOL)@t{aFlag}@* @ @ @ @ @b{withMinXMargin:} (float)@t{aMargin} Add a view to the box, enabling X Resizing only if @code{flag} is @code{YES}, and a MinXMargin @code{aMargin}. If @code{aFlag} is @code{YES} the [view and its margins] should be resized in the horizontal direction when the GSHbox is resized in the horizontal direction. If @code{aFlag} is @code{NO} the view is never X-resized and always left in its original width. The default is @code{YES}. The min X margin is used to separate the view from the preceding one. The first view added to the box has no min X margin; if you try setting one for it, it is ignored (zero is used instead). When views are added to the @code{GSHbox}, it might happen that some of the added views have a greater height than others. When this happens, the @code{GSHbox} resizes all the views to the highest height. As usual, each view is resized with its margins; the effect of the resizing on each view is determined by the autoresizing mask of the view. The classical options are @table @code @item (NSViewMinYMargin | NSViewMaxYMargin) Center the view vertically @item NSViewMinYMargin Flush the view up (down if the @code{GSHbox} is flipped) @item NSViewMaxYMargin Flush the view down (up if the @code{GSHbox} is flipped) @item NSViewHeightSizable Expand the view to the whole height @end table (you may need to @code{OR} these masks with the mask you use in the horizontal direction, if you use any). @node Adding a Separator, Setting Margins, Adding a View, GSHbox Method Description @subsubsection Adding a Separator @noindent -(void) @b{addSeparatorWithMinXMargin:} (float)@t{aMargin} Add a separator (a vertical groove line encompassing all the height of the @code{GSHbox}) to the @code{GSHbox}, inserting a margin @code{aMargin} between the separator and the last added view. @noindent -(void) @b{addSeparator} Add a separator with the default MinXMargin. @node Setting Margins, Getting the Minimum Size, Adding a Separator, GSHbox Method Description @subsubsection Setting Margins @noindent -(void) @b{setDefaultMinXMargin:} (float)@t{aMargin} If you change the default min X margin with this method, it will get used for all the views you add after changing it, when no particular margins are specified for those views. This method does nothing on already added views; it only changes an internal @code{GSHbox} instance variable which is used only when a new view is added to the @code{GSHbox} without any min X margin specified. Each @code{GSHbox} has its own default min X margin. @node Getting the Minimum Size, Resizing the Box, Setting Margins, GSHbox Method Description @subsubsection Getting the Minimum Size @noindent -(NSSize) @b{minimumSize} See the @code{GSTable} class description. @node Resizing the Box, Getting the Number of Views, Getting the Minimum Size, GSHbox Method Description @subsubsection Resizing the Box @noindent -(void) @b{sizeToFit} See the @code{GSTable} class description. @node Getting the Number of Views, , Resizing the Box, GSHbox Method Description @subsubsection Getting the Number of Views @noindent -(int) @b{numberOfViews} Return the number of views (separators included) in the GSHbox. @node GSTable, GSVbox, GSHbox, Classes @section GSTable Reference @menu * GSTable Class:: * GSTable Overview:: * Advanced Description of GSTable:: * GSTable Method Description:: @end menu @node GSTable Class, GSTable Overview, GSTable, GSTable @subsection @code{GSTable} Class @display @b{Inherits from:} @code{NSView: NSResponder: NSObject}@* @b{Conforms to:} @code{NSCoding} (from @code{NSResponder}), @code{NSObject} (from @code{NSObject})@* @b{Declared in:} @file{AppKit/GSTable.h} @end display @code{GSTable} is a GNUstep GUI extension to the OpenStep specification. @node GSTable Overview, Advanced Description of GSTable, GSTable Class, GSTable @subsection Overview of the @code{GSTable} Class A @code{GSTable} object is used to control the disposition (position and size) of a group of @code{NSView}s. The @code{GSTable} object offers two main facilities to the programmer: @itemize @bullet @item with a @code{GSTable} object, you do not need to specify the exact position and size of each view. You only specify the logical position, relative to the other views in the table. The actual frame of each view is then computed by the @code{GSTable} at run time. @item when the @code{GSTable} is resized (for example, because the user has resized the window in which the @code{GSTable} is), the @code{GSTable} takes care of moving and resizing all its views automatically. This is done in much a advanced and customizable way than in the usual standard @code{NSView}'s autoresizing mechanism. @end itemize You create a @code{GSTable} instance with a certain number of rows and columns. The @code{GSTable} object itself is invisible; it is only a logical device used to specify the subview position. Then, you place one by one the views you want to control in the @code{GSTable}, by calling a method of the family @code{-putView:atRow:column:}. Before placing a view in the table, you should resize it to the minimum comfortable size you want it to have. The table then automatically places the views, organizing them in well-ordered columns and rows. The initial size of the @code{GSTable} is zero; each time you put a view in the @code{GSTable}, the @code{GSTable} recomputes sizes and as a result resizes itself so that it exactly fits the views it contains. You should not force a @code{GSTable} in a size different from the one it has automatically computed. The only acceptable, reasonable and meaningful way of resizing a @code{GSTable} is through the appropriate @code{-resizeWithOldSuperviewSize:} message when the @code{GSTable} is in the view hierarchy. When you add a view, you may specify some particular margins to be used for that view. If nothing is specified, the view is added to the table with the margins of 0. You should think of each view and its margins as a whole. A position in the @code{GSTable} is free or filled with a view and its margins. The @code{GSTable} itself knows what is the minimum size it needs to have in order to comfortably display the views it contains. You may get this size by calling the method @code{-minimumSize}. When first filled, the table has this minimum size. If in any moment you want the table to restore itself to this size, you should invoke the method @code{-sizeToFit}. When the @code{GSTable} receives a @code{-resizeWithOldSuperviewSize:} message, it automatically rearranges the views it contains: @itemize @bullet @item If the new width or height is equal or less than the table's minimum width or height, the @code{GSTable} simply arranges its views in the initial position. In other words, the @code{GSTable} refuse to resize below its minimum width or height. If you do that, part of the @code{GSTable} is clipped. @item If the new width or height is bigger than the table's minimum width or height, the space in excess is equally distributed between the columns or rows which have X (or Y) resizing enabled. When a column or a row is resized, each view in the column or row is resized together with its margins. By setting the autoresizingMask of each view, you may decide how the resizing operation will act on that particular view and its margins. For example, setting the autoresizingMask to @code{NSViewWidthSizable | NSViewHeightSizable} will always leave the margins fixed to their initial dimensions, and expand/reduce only the view, in all directions. Setting the autoresizingMask to @code{NSViewMinXMargin | NSViewMaxXMargin} @code{| NSViewSizable | NSViewHeightSizable} will instead expand/reduce both the margins and the view in the horizontal direction, but leave the margins fixed and expand/reduce only the view in the vertical direction. Whatever the autoresizingMask and the amount of the resizing, views and margins are never resized below their minimum comfortable size, as explained above. For more information on the autoresizingMask, please refer to the description of the @code{-setAutoresizingMask:} method of the @code{NSView} class. @end itemize You may find practical examples of the use of the @code{GSTable} class in the @file{Testing} directory of the source code of the GNUstep Library. @node Advanced Description of GSTable, GSTable Method Description, GSTable Overview, GSTable @subsection Advanced Description of @code{GSTable} We call any view which is added to the @code{GSTable} a @dfn{prisoner}. The purpose of the @code{GSTable} is to effectively manage its prisoners. To do so, the @code{GSTable} creates a special view, called a @dfn{jail}, for each prisoner. The jails are subviews of the @code{GSTable}; each prisoner, when added to the @code{GSTable}, is made a subview of its jail. The @code{GSTable} always moves and resizes directly the jails. The moving is automatically transmitted to the prisoners, which are subviews of the jails; the resizing is transmitted through the usual autoresizing machinery, because the jails always have autoresizing of subviews turned on. This works because if a prisoner sends to its superview a @code{-frame} message, the frame of the jail (and @emph{not} the frame of the @code{GSTable}) is returned, so that each prisoner will autoresize itself in its jail frame. Moreover, any prisoner, being a subview of its jail, is clipped in its jail frame. If a prisoner draws something out of its jail frame, the output is discarded by the usual subview/view clipping machinery. This prevents the prisoners from disturbing each other. The dimension of the jail is the dimension of the prisoner plus its margins. Since the @code{GSTable} manages directly the jails, each prisoner is managed together with its margins. When the jail is resized, the prisoner receives a @code{-resizeWithOldSuperviewSize:}, which makes it resize itself and its margins in the new jail size, according to its autoresizingMask. @node GSTable Method Description, , Advanced Description of GSTable, GSTable @subsection @code{GSTable} Method Description @menu * Initializing a GSTable:: * Putting Views in a GSTable:: * Setting Borders:: * Minimum Size:: * Resizing:: * Setting Row and Column Expand Flag:: * Adding Rows and Columns to GSTable:: * Getting GSTable Row and Column Number:: @end menu @c TODO: Add to texinfo a native command to produce Objective-C method @c declarations. @node Initializing a GSTable, Putting Views in a GSTable, GSTable Method Description, GSTable Method Description @subsubsection Initializing a @code{GSTable} @noindent -(id) @b{initWithNumberOfRows:} (int)@t{rows}@* @ @ @ @b{numberOfColumns:} (int)@t{columns} Initialize a @code{GSTable} with @code{columns} columns and @code{rows} rows. If @code{columns} or @code{rows} is negative or null, a warning is issued and a default of 2 is used instead. @noindent -(id) @b{init} Initialize a @code{GSTable} with 2 columns and 2 rows. @node Putting Views in a GSTable, Setting Borders, Initializing a GSTable, GSTable Method Description @subsubsection Putting Views in a @code{GSTable} Use these methods to put views in the @code{GSTable}: @noindent -(void) @b{putView:} (NSView *)@t{aView}@* @ @ @ @ @b{atRow:} (int)@t{row}@* @ @ @ @ @b{column:} (int)@t{column} Put @code{aView} in the @code{GSTable}, in the specified @code{row} and @code{column}. Zero (0) margins are used. If the column @code{column} (or the row @code{row}) is not enough big to fully display @code{aView} and its margins, the column (or the row) is resized (regardless of the fact that X or Y Resizing is Enabled or not). It is understood that this will affect each view (and its margins) in the column (or row) according to the autoresizing mask of each view. @noindent -(void) @b{putView:} (NSView *)@t{aView}@* @ @ @ @ @b{atRow:} (int)@t{row}@* @ @ @ @ @b{column:} (int)@t{column}@* @ @ @ @ @b{withMargins:} (float)@t{margins} Put @code{aView} in the @code{GSTable}, using @code{margins} as margin in all directions: left, right, top, bottom. @noindent -(void) @b{putView:} (NSView *)@t{aView}@* @ @ @ @ @b{atRow:} (int)@t{row}@* @ @ @ @ @b{column:} (int)@t{column}@* @ @ @ @ @b{withXMargins:} (float)@t{xMargins}@* @ @ @ @ @b{yMargins:} (float)@t{yMargins}@* Put @code{aView} in the @code{GSTable}, using @code{xMargins} as the left and right margins, and @code{yMargins} as the top and bottom margins. @noindent -(void) @b{putView:} (NSView *)@t{aView}@* @ @ @ @ @b{atRow:} (int)@t{row}@* @ @ @ @ @b{column:} (int)@t{column}@* @ @ @ @ @b{withMinXMargin:} (float)@t{minXMargin}@* @ @ @ @ @b{maxXMargin:} (float)@t{maxXMargin}@* @ @ @ @ @b{minYMargin:} (float)@t{minYMargin}@* @ @ @ @ @b{maxYMargin:} (float)@t{maxYMargin} Put @code{aView} in the @code{GSTable}, using the specified margins. The names for the margins are chosen as to be as close as possible to the autoresizingMask convention. The margins are to be interpreted as follows: @table @code @item minXMargin Left Margin @item maxXMargin Right Margin @item minYMargin Lower Margin (Upper if view is flipped) @item maxYMargin Upper Margin (Lower if view is flipped) @end table @node Setting Borders, Minimum Size, Putting Views in a GSTable, GSTable Method Description @subsubsection Setting Borders @noindent -(void) @b{setBorder:} (float)@t{aBorder} Set the @code{GSTable} up, bottom, left and right borders to the same value @t{aBorder}. The @code{GSTable} is immediately updated. If @code{aBorder} is negative, the border is reset to the default, which is zero (0). The border is simply unfilled space; it is measured in the @code{GSTable} coordinate system. @noindent -(void) @b{setXBorder:} (float)@t{aBorder} Set the @code{GSTable} left and right borders to @t{aBorder}. If @t{aBorder} is negative, the border is reset to zero. The @code{GSTable} is immediately updated. @noindent -(void) @b{setYBorder:} (float)@t{aBorder} Same as @code{setXBorder:} but set the up and bottom borders. @noindent -(void) @b{setMinXBorder:} (float)@t{aBorder} Same as @code{setXBorder:} but set only the left border. @noindent -(void) @b{setMaxXBorder:} (float)@t{aBorder} Same as @code{setXBorder:} but set only the right border. @noindent -(void) @b{setMinYBorder:} (float)@t{aBorder} Same as @code{setXBorder:} but set only the lower border (upper if the @code{GSTable} is flipped). @noindent -(void) @b{setMaxYBorder:} (float)@t{aBorder} Same as @code{setXBorder:} but set only the upper border (lower if the @code{GSTable} is flipped). @node Minimum Size, Resizing, Setting Borders, GSTable Method Description @subsubsection Minimum Size. @noindent -(NSSize) @b{minimumSize} Return the minimum size the Table should be resized to. Trying to resize the Table below this size will only result in clipping (ie, making it disappear) part of the Table. @node Resizing, Setting Row and Column Expand Flag, Minimum Size, GSTable Method Description @subsubsection Resizing. @noindent -(void) @b{sizeToFit} The table is resized to its minimum size; the views (with their margins) are moved and resized to their minimum size so that they exactly pack in the table. @node Setting Row and Column Expand Flag, Adding Rows and Columns to GSTable, Resizing, GSTable Method Description @subsubsection Setting Row and Column Expand Flag When the @code{GSTable} is resized, the extra space is equally divided between the Rows and Columns which have the X (or Y) resizing enabled. The following methods let you enable/disable the X (or Y) resizing of each row and column in the @code{GSTable}. Note that when the @code{GSTable} is first created, all its columns and rows have by default resizing enabled. @noindent -(void) @b{setXResizingEnabled:} (BOOL)@t{aFlag}@* @ @ @ @ @b{forColumn:} (int)@t{aColumn} Enable/disable X Resizing for the column @code{aColumn} according to @code{aFlag}. Note: at present, enabling/disabling X resizing after the table has been put in the view hierarchy is not supported. @noindent -(void) @b{setYResizingEnabled:} (BOOL)@t{aFlag}@* @ @ @ @ @b{forRow:} (int)@t{aRow} Enable/disable Y Resizing for the row @code{aRow} according to @code{aFlag}. Note: at present, enabling/disabling Y resizing after the table has been put in the view hierarchy is not supported. @noindent -(BOOL) @b{isXResizingEnabledForColumn:} (int)@t{aColumn} Return whether X resizing is enabled for the column @code{aColumn}. @noindent -(BOOL) @b{isYResizingEnabledForRow:} (int)@t{aRow} Return whether Y resizing is enabled for the row @code{aRow}. @node Adding Rows and Columns to GSTable, Getting GSTable Row and Column Number, Setting Row and Column Expand Flag, GSTable Method Description @subsubsection Adding Rows and Columns These methods should be used to add more rows and columns to the table. Remember that it is faster to create a @code{GSTable} with the right number of rows and columns from the beginning. @noindent -(void) @b{addRow} Add a row to the @code{GSTable}. The row is added void, with zero height and Y Resizing enabled. @noindent -(void) @b{addColumn} Add a column to the @code{GSTable}. The column is added void, with zero width and X Resizing enabled. @node Getting GSTable Row and Column Number, , Adding Rows and Columns to GSTable, GSTable Method Description @subsubsection Getting Row and Column Number @noindent -(int) @b{numberOfRows} Return the number of rows in the @code{GSTable}. @noindent -(int) @b{numberOfColumns} Return the number of columns in the @code{GSTable}. @node GSVbox, , GSTable, Classes @section GSVbox Reference @menu * GSVbox Class:: * GSVbox Overview:: @end menu @node GSVbox Class, GSVbox Overview, GSVbox, GSVbox @subsection @code{GSVbox} Class @display @b{Inherits from:} @code{GSTable: NSView: NSResponder: NSObject}@* @b{Conforms to:} @code{NSCoding} (from @code{NSResponder}), @code{NSObject} (from @code{NSObject})@* @b{Declared in:} @file{AppKit/GSVbox.h} @end display @code{GSVbox} is a GNUstep GUI extension to the OpenStep specification. @node GSVbox Overview, , GSVbox Class, GSVbox @subsection @code{GSVbox} Overview A @code{GSVbox} is completely analogue to a @code{GSHbox}. It implements the same methods; the only different is that it packs views from bottom to top (from top to bottom if flipped). It implements the following methods: @noindent -(id) @b{init} @noindent -(void) @b{setBorder:} (float)@t{aBorder} @noindent -(void) @b{setXBorder:} (float)@t{aBorder} @noindent -(void) @b{setYBorder:} (float)@t{aBorder} @noindent -(void) @b{setMinXBorder:} (float)@t{aBorder} @noindent -(void) @b{setMaxXBorder:} (float)@t{aBorder} @noindent -(void) @b{setMinYBorder:} (float)@t{aBorder} @noindent -(void) @b{setMaxYBorder:} (float)@t{aBorder} @noindent -(void) @b{addView:} (NSView *)@t{aView} @noindent -(void) @b{addView:} (NSView *)@t{aView}@* @ @ @ @ @b{enablingYResizing:} (BOOL)@t{aFlag} @noindent -(void) @b{addView:} (NSView *)@t{aView}@* @ @ @ @ @b{withMinYMargin:} (float)@t{aMargin} @noindent -(void) @b{addView:} (NSView *)@t{aView}@* @ @ @ @ @b{enablingYResizing:} (BOOL)@t{aFlag}@* @ @ @ @ @b{withMinYMargin:} (float)@t{aMargin} @noindent -(void) @b{addSeparator} @noindent -(void) @b{addSeparatorWithMinYMargin:} (float)@t{aMargin} @noindent -(void) @b{setDefaultMinYMargin:} (float)@t{aMargin} @noindent -(NSSize) @b{minimumSize} @noindent -(void) @b{sizeToFit} @noindent -(int) @b{numberOfView} See the documentation for the corresponding @code{GSHbox} class methods for more information. @node Tools, Implementation, Classes, Top @chapter Tools Included with gstep-gui. @node Implementation, Setup, Tools, Top @chapter Implementation Details Following are some implementation details of the GUI library. These will mostly be of interest to developers of the GUI library itself. @menu * Drag and Drop:: * NSWorkspace:: @end menu @node Drag and Drop, NSWorkspace, Implementation, Implementation @section Drag and Drop The drag types info for each view is kept in a global map table (protected by locks) and can be accessed by the backend library using the function - @smallexample NSArray *GSGetDragTypes(NSView *aView); @end smallexample Drag type information for each window (a union of the drag type info for all the views in the window) is maintained in the graphics context. The backend can get this information (as a counted set) using - @smallexample - (NSCountedSet*) _dragTypesForWindow: (int)winNum; @end smallexample Whenever a DnD aware view is added to, or removed from a window, the type information for that view is added to/removed from the type information for the window, altering the counted set. If the alteration results in a change in the types for the window, the method making the change returns YES. @smallexample - (BOOL) _addDragTypes: (NSArray*)types toWindow: (int)winNum; - (BOOL) _removeDragTypes: (NSArray*)types fromWindow: (int)winNum; @end smallexample The backend library should therefore override these methods and call 'super' to handle the update. If the call to the super method returns YES, the backend should make any changes as appropriate (in the case of the xdnd protocol this means altering the XdndAware property of the X window). You will notice that these methods use the integer window number rather than the NSWindow object - this is for the convenience of the backend library which should (eventually) use window numbers for everything @node NSWorkspace, , Drag and Drop, Implementation @section NSWorkspace Here is (I think) the current state of the code (largely untested) - The make_services tool examines all applications (anything with a .app, .debug, or .profile suffix) in the system, local, and user Apps Directories. In addition to the cache of services information, it builds a cache of information about known applications (including information about file types they handle). NSWorkspace reads the cache and uses it to determine which application to use to open a document and which icon to use to represent that document. The NSWorkspace API has been extended to provide methods for finding/setting the preferred icon/application for a particular file type. NSWorkspace will use the 'best' icon/application available. To determine the executable to launch, if there was an Info-gnustep.plist/Info.plist in the app wrapper and it had an NSExecutable field - use that name. Otherwise, try to use the name of the app - eg. foo.app/foo The executable is launched by NSTask, which handles the addition of machine/os/library path components as necessary. To determine the icon for a file, use the value from the cache of icons for the file extension, or use an 'unknown' icon. To determine the icon for a folder, if the folder has a '.app', '.debug' or '.profile' extension - examine the Info.plist file for an 'NSIcon' value and try to use that. If there is no value specified - try foo.app/foo.tiff' or 'foo.app/.dir.tiff' If the folder was not an application wrapper, just try the .dir.tiff file. If no icon was available, use a default folder icon or a special icon for the root directory. The information about what file types an app can handle needs to be in the MacOS-X format in the Info-gnustep.plist/Info.plist for the app - see @url{http://developer.apple.com/techpubs/macosxserver/System/Documentation/Developer/YellowBox/ReleaseNotes/InfoPlist.html}. In the NSTypes fields, I used NSIcon (the icon to use for the type) NSUnixExtensions (a list of file extensions corresponding to the type) and NSRole (what the app can do with documents of this type). In the AppList cache, I generate a dictionary, keyed by file extension, whose values are the dictionaries containing the NSTypes dictionaries of each of the apps that handle the extension. I tested the code briefly with the FileViewer app, and it seemed to provide the icons as expected. With this model the software doesn't need to monitor loads of different files, just register to recieve notifications when the defaults database changes, and check an appropriate default value. At present, there are four hidden files used by the software: @table @samp @item ~/GNUstep/Services/.GNUstepAppList Cached information about applications and file extensions. @item ~/GNUstep/Services/.GNUstepExtPrefs User preferences for which apps/icons should be used for each file extension. @item ~/GNUstep/Services/.GNUstepServices Cache of services provides by apps and services daemons @item ~/GNUstep/Services/.GNUstepDisabled User settings to determine which services should not appear in the services menu. @end table Each of these is a serialized property list. Almost forgot - Need to modify NSApplication to understand '-GSOpenFile ...' as an instruction to open the specified file on launching. Need to modify NSWorkspace to supply the appropriate arguments when launching a task rather than using the existing mechanism of using DO to request that the app opens the file. When these changes are made, we can turn any program into a pseudo-GNUstep app by creating the appropriate app wrapper. An app wrapper then need only contain a shell-script that understands the -GSOpenFile argument and uses it to start the program - though provision of a GNUstep-info.plist and various icons would obviously make things prettier. For instance - you could set up xv.app to contain a shellscript 'xv' that would start the real xv binary passing it a file to open if the -GSOpenFile argument was given. The Info-gnustep.plist file could look like this: @example @{ NSExecutable = "xv"; NSIcon = "xv.tiff"; NSTypes = ( @{ NSIcon = "tiff.tiff"; NSUnixExtensions = ( tiff, tif ); @}, @{ NSIcon = "xbm.tiff"; NSUnixExtensions = ( xbm ); @} ); @} @end example @node Setup, Contributing, Implementation, Top @chapter Special Setup Instructions. @menu * Keyboard Modifiers:: * Window Manager:: @end menu @node Keyboard Modifiers, Window Manager, Setup, Setup @section Keyboard Modifiers This section applies only to the xgps and the xdps backend. @subsection Default Settings The OPENstep specification requires 3 main different keyboard modifiers: @key{CONTROL}, @key{COMMAND} and @key{ALTERNATE}. @c @itemize @bullet @item @key{COMMAND} is used to enter key equivalents (keyboard shortcuts for menus or buttons); for example, usually 'Quit' on the main menu of an application is bound to 'q', so you may usually quit a GNUstep application by pressing @kbd{Command - q}. @item @key{CONTROL} and @key{ALTERNATE} are two additional modifiers. A typical use of @key{ALTERNATE} is to scroll by pages rather than by lines; you have to press @key{ALTERNATE} while acting on a scrollbar with the mouse. @end itemize @c By default, GNUstep uses @code{Control_L} (left Ctrl) and @code{Control_R} (right Ctrl) as @key{CONTROL}, @code{Alt_L} (left alt) as @key{COMMAND}, and @code{Alt_R} (right alt, sometimes called AltGr) as @key{ALTERNATE}. As a special exception, if @code{Alt_R} is not bound to any key on your keyboard, GNUstep will try to use @code{Mode_switch} for @key{ALTERNATE} instead. If this layout does not work for you, because your keyboard misses some of these keys, or they have different X names or they conflict heavily with your window manager shortcuts (or for any other reason), read on. @subsection Changing the Default Settings Under GNUstep, you may change the default as you wish: you may choose which keys of your keyboard you want to use for @key{CONTROL}, @key{COMMAND} and @key{ALTERNATE} (You may even use different keys for different GNUstep applications, without conflict). These settings are internal to GNUstep, and will not influence the behaviour of other X apps. You may choose up to 2 keys per modifier. Note that, if your keyboard is properly set up for X, you should @emph{not} need to remap your X keyboard to use GNUstep. By changing the defaults, you should be able to use GNUstep whatever the X keyboard mapping might be. What you have to do, is simply to instruct GNUstep to use different keys for @key{CONTROL}, @key{COMMAND} and @key{ALTERNATE}. The keys to use are determined at the application startup, by reading the user defaults database. To set the keys which will act as @key{CONTROL} you have to set @code{GSFirstControlKey} and @code{GSSecondControlKey}; and similarly for the other keys: @table @code @item CONTROL @code{GSFirstControlKey} @code{GSSecondControlKey} @item COMMAND @code{GSFirstCommandKey} @code{GSSecondCommandKey} @item ALTERNATE @code{GSFirstAlternateKey} @code{GSSecondAlternateKey} @end table Valid values are all the standard strings for X keys. To disable completely a key, use @code{NoSymbol} as preference. Each value which you do not explicity set is substituted with its default value. The default values are: @table @code @item GSFirstControlKey @code{Control_L} @item GSSecondControlKey @code{Control_R} @item GSFirstCommandKey @code{Alt_L} @item GSSecondCommandKey @code{NoSymbol} @item GSFirstAlternateKey @code{Alt_R} (or @code{Mode_switch} if there is no @code{Alt_R}) @item GSSecondAlternateKey @code{NoSymbol} @end table What could go wrong is for example that you don't have an @code{Alt_L} key. With the default settings, you will not be able to enter the @key{COMMAND} key (which is quite an important key). What you can do in this case is to use @code{Control_R} as @key{COMMAND}, giving the following commands (from the command line): @smallexample defaults write NSGlobalDomain GSFirstCommandKey Control_R defaults write NSGlobalDomain GSSecondControlKey NoSymbol @end smallexample These commands write in the GNUstep user database; the information will be used every time you start a GNUstep application. The first line sets @code{GSFirstCommandKey} to @code{Control_R}, which makes @code{Control_R} to be read as @key{COMMAND}. The second line disables the second control key, which would otherwise be bound to @code{Control_R} by default. If you omit it, @code{Control_R} will be used at the same time as @key{COMMAND} and as @key{CONTROL}, which is not very useful. To delete these preferences and restore the defaults, use @smallexample defaults delete NSGlobalDomain GSFirstCommandKey defaults delete NSGlobalDomain GSSecondControlKey @end smallexample To get a list of currently set defaults, you may use @smallexample defaults read @end smallexample The list might be very long; you may want to extract only setting for the @code{GSFirstCommandKey}, for example: @smallexample defaults read | grep GSFirstCommandKey @end smallexample A thing which could go wrong if you are trying to use a setting different from the default, and you do not know much about X, is that you can't find out the name of one of your key. In this case, you may try having a look at the output of programs like @code{xmodmap} or @code{xkeycaps}; even if you do not understand it completely, the output can inspire the right guessing. A problem you are likely to encounter is that of conflicts with the window manager keyboard shortcuts. Good window managers let you change the keyboard shortcuts, so you may move the wm shortcuts that you do not use to keys which do not conflict (at least not too much) with GNUstep. @node Window Manager, , Keyboard Modifiers, Setup @section Window Manager Recommended Configuration If you are using GNUstep GUI library with the Window Maker window manager it is recommended that you set the Window Maker option "Input Focus Mouse" (under "Window Focus Preferences") to "Click Window To Focus". If you are using another window manager, look for a similar option. @node Contributing, Concept Index, Setup, Top @chapter Contributing Contributing code is not difficult. Here are some general guidelines: @itemize @bullet @item FSF must maintain the right to accept or reject potential contributions. Generally, the only reasons for rejecting contributions are cases where they duplicate existing or nearly-released code, contain unremovable specific machine dependencies, or are somehow incompatible with the rest of the library. @item Acceptance of contributions means that the code is accepted for adaptation into libgnustep-gui. FSF must reserve the right to make various editorial changes in code. Very often, this merely entails formatting, maintenance of various conventions, etc. Contributors are always given authorship credit and shown the final version for approval. @item Contributors must assign their copyright to FSF via a form sent out upon acceptance. Assigning copyright to FSF ensures that the code may be freely distributed. @item Assistance in providing documentation, test files, and debugging support is strongly encouraged. @end itemize Extensions, comments, and suggested modifications of existing libgnustep-gui features are also very welcome. @node Concept Index, , Contributing, Top @unnumbered Concept Index @printindex cp @summarycontents @contents @bye