libs-gui/Documentation/gnustep-gui.texi

1440 lines
53 KiB
Text
Raw Normal View History

\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
* gstep-gui:: The GNUstep GUI Library
@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 <n.pero@@mi.flashnet.it>"]}).
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 X-Windows based 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