     START-INFO-DIR-ENTRY
     * gstep-gui::                      The GNUstep GUI Library
     END-INFO-DIR-ENTRY

     [file version.texi not included]

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.

gstep-gui
*********

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.

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 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.

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.

Special Features of GUI Classes.
********************************

NSApplication
=============

Standard Info Panel
-------------------

GNUstep NSApplication provides the following two methods to easily create a standard Info Panel for your application:

- (void) orderFrontStandardInfoPanel: (id)sender

Invokes orderFrontStandardInfoPanelWithOptions: with a 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.

- (void) orderFrontStandardInfoPanelWithOptions: (NSDictionary *)dictionary

Orders front the standard info panel for the application, taking the needed information from the 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 dictionary are:

ApplicationName: A string with the name of the application (eg, @"Gorm").  If not available, the Info-gnustep.plist file is searched for the value of ApplicationName; if this fails, the Info-gnustep.plist file is searched for the value of NSHumanReadableShortName; if this also fails, the string returned by [[NSProcessInfo processInfo] processName] is used.

ApplicationDescription: A string with a very short description of the application (eg, @"GNUstep Graphics Objects Relationship Modeller").  If not available, Info-gnustep.plist is searched for that key; if this fails, no application description is shown.

ApplicationIcon: An image to be shown near the title.  If not available, Info-gnustep.plist is looked for ApplicationIcon; if this fails, [NSApp applicationIconImage] is used instead.  Since this is what you usually want, you usually do not need to set the ApplicationIcon key/value in the dictionary.

ApplicationRelease: A string with the name of the application, release included (eg, @"Gorm 0.1").  If not available, the value for ApplicationVersion is used instead.  If this fails, Info-gnustep.plist is looked for ApplicationRelease or (failing this) for NSAppVersion.  If all fails, "Unknown" is used.

FullVersionID: A string with the full version of the application (eg, @"0.1.2b" or @"snap011100").  If not available, Version is used instead.  If this fails, Info-gnustep.plist is looked for NSBuildVersion.  If all fails, no full version is shown.

Authors: An array of strings, each one with the name of an author (eg, [NSArray arrayWithObject: @"Nicola Pero <n.pero@mi.flashnet.it>"]). If not found, Info-gnustep.plist is looked for Authors, if this fails, @"Unknown" is displayed.

URL: [This field is still under work, so it might be changed] A string with an URL (eg, @"See http://www.gnustep.org").

Copyright: A string with copyright owners (eg, @"Copyright (C) 2000 The Free Software Foundation, Inc.").  Support for multiple line strings is planned but not yet available.  If not found, Info-gnustep.plist is searched for Copyright and then (failing this) for NSHumanReadableCopyright.  If all fails, @"Copyright Information Not Available" is used.

CopyrightDescription: A string describing the kind of copyright (eg, @"Released under the GNU General Public License 2.0").  If not available, Info-gnustep.plist is looked for CopyrightDescription.  If this fails, no copyright description is shown.

For compatibility reasons only, the following MacOSX API is also available:

- (void) orderFrontStandardAboutPanel: (id)sender

- (void) orderFrontStandardAboutPanelWithOptions: (NSDictionary *)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 Info... item in the Info menu.

NSBrowserCell
=============

GSBrowserCellFontify
--------------------

GNUstep NSBrowserCell has an experimental feature (disabled by default), which you may turn on by setting the GSBrowserCellFontify user default to YES.

To turn it on, issue the command:

     defaults write NSGlobalDomain GSBrowserCellFontify YES

To turn it off:

     defaults delete NSGlobalDomain GSBrowserCellFontify

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.

NSSavePanel
===========

GSSavePanelShowProgress
-----------------------

GNUstep NSSavePanel has an experimental feature (disabled by default), which you may turn on by setting the GSSavePanelShowProgress user default to 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.

GSHbox Reference
================

GSHbox Class
------------

     Inherits from: GSTable: NSView: NSResponder: NSObject

     Conforms to:  NSCoding (from NSResponder)

            NSObject (from NSObject)

     Declared in: AppKit/GSHbox.h

GSHbox is a GNUstep GUI extension to the OpenStep specification.

Overview of the GSHbox Class
----------------------------

GSHbox is a subclass of GSTable meant to provide an extremely simplified API for managing rows of views.  The only real difference between a GSHbox and a GSTable with 1 row is that GSHbox has a much simpler, easier and less powerful API. This difference makes programming with GSHbox (and GSVbox) much faster than dealing directly with the underlying GSTable.

If you use GSHbox, it is to take advantage of the simplified API. You shouldn't use GSTable methods with GSHbox (exception: methods explicitly listed in this documentation), because GSHbox is supposed to manage those methods for you.  If you need the power of the full GSTable API, you should simply be using GSTable and not GSHbox.

A GSHbox is an invisible view (a logical device) which can contain some views.  The GSHbox controls the position and sizes of these views so that they are lined up in a row.

To initialize a GSHbox, you should always use -init method.  Don't use GSTable methods.  The correct way to start using a new GSHbox is simply:

     hbox = [GSHbox new];

(well, of course, autoreleasing it if necessary).  You add a view to a GSHbox using the method -addView: and its variants.  The views you add to a GSHbox are placed by the 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 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 GSHbox is zero; each time you add a view in the GSHbox, the GSHbox resizes itself to fit the new contents.  Usually, you simply add objects to the GSHbox, and let it compute its size (this is the minimum size); you may get this resulting size by

     size = [yourHBox size];

for example, if the 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 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 GSHbox is through -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 -addView:withMinXMargin: you may tell the GSHbox to insert some space (a margin) between the view you are adding and the previous one (the one at its left).

If what you want is space around the GSHbox, and not between views in the GSHbox, you don't want a margin but a border; you should then use -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 -setMinXBorder: and similar methods).

A useful feature of GSHbox is that it supports separators. This facility is not directly available in GSTable (to add separators to a GSTable you need to create and handle them yourself).  A 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 -addSeparator.  The separator is put at the right of the last added view.

To use GSHbox proficiently, it is crucial to set correctly the autoresizing mask of each view before adding it to the GSHbox.

The GSHbox treats each view and its margins as a whole (see the GSTable class description for more information).

When the GSHbox is resized in the vertical direction (as a consequence of user intervertion, for example), what happens is:

  * if the new height is less than the minimum height of the 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.

  * if the new height is greater than the GSHbox's minimum height, the 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 autoresizingMask of each view that you add, you are able to control exactly how the resizing effects each view and its margins.

When the GSHbox is resized in the horizontal direction, its behaviour is as follows:

  * 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.

  * 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 NO value to the option 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 YES for 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.

GSHbox Method Description
-------------------------

Initializing
............

-(id) init

Initialize the GSHbox. This is the only allowed initialization method for GSHbox.

Setting the Box Borders
.......................

-(void) setBorder: (float)aBorder

See the GSTable class description.

-(void) setXBorder: (float)aBorder

See the GSTable class description.

-(void) setYBorder: (float)aBorder

See the GSTable class description.

-(void) setMinXBorder: (float)aBorder

See the GSTable class description.

-(void) setMaxXBorder: (float)aBorder

See the GSTable class description.

-(void) setMinYBorder: (float)aBorder

See the GSTable class description.

-(void) setMaxYBorder: (float)aBorder

See the GSTable class description.

Adding a View
.............

-(void) addView: (NSView *)aView

Add a view to the box, enabling X resizing, and with the default MinXMargin.

-(void) addView: (NSView *)aView

    enablingXResizing: (BOOL)aFlag

Add a view to the box with the default MinXMargin, enabling X resizing only if aFlag is YES,

-(void) addView: (NSView *)aView

    withMinXMargin: (float)aMargin

Add a view to the box with aMargin MinXMargin, and enabing X resizing.

-(void) addView: (NSView *)aView

    enablingXResizing: (BOOL)aFlag

    withMinXMargin: (float)aMargin

Add a view to the box, enabling X Resizing only if flag is YES, and a MinXMargin aMargin.  If aFlag is YES the [view and its margins] should be resized in the horizontal direction when the GSHbox is resized in the horizontal direction.  If aFlag is NO the view is never X-resized and always left in its original width.  The default is 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 GSHbox, it might happen that some of the added views have a greater height than others.  When this happens, the 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

(NSViewMinYMargin | NSViewMaxYMargin)
     Center the view vertically

NSViewMinYMargin
     Flush the view up (down if the GSHbox is flipped)

NSViewMaxYMargin
     Flush the view down (up if the GSHbox is flipped)

NSViewHeightSizable
     Expand the view to the whole height

(you may need to OR these masks with the mask you use in the horizontal direction, if you use any).

Adding a Separator
..................

-(void) addSeparatorWithMinXMargin: (float)aMargin

Add a separator (a vertical groove line encompassing all the height of the GSHbox) to the GSHbox, inserting a margin aMargin between the separator and the last added view.

-(void) addSeparator

Add a separator with the default MinXMargin.

Setting Margins
...............

-(void) setDefaultMinXMargin: (float)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 GSHbox instance variable which is used only when a new view is added to the GSHbox without any min X margin specified.  Each GSHbox has its own default min X margin.

Getting the Minimum Size
........................

-(NSSize) minimumSize

See the GSTable class description.

Resizing the Box
................

-(void) sizeToFit

See the GSTable class description.

Getting the Number of Views
...........................

-(int) numberOfViews

Return the number of views (separators included) in the GSHbox.

GSTable Reference
=================

GSTable Class
-------------

     Inherits from: NSView: NSResponder: NSObject

     Conforms to:  NSCoding (from NSResponder),
     NSObject (from NSObject)

     Declared in: AppKit/GSTable.h

GSTable is a GNUstep GUI extension to the OpenStep specification.

Overview of the GSTable Class
-----------------------------

A GSTable object is used to control the disposition (position and size) of a group of NSViews.  The GSTable object offers two main facilities to the programmer:

  * with a 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 GSTable at run time.

  * when the GSTable is resized (for example, because the user has resized the window in which the GSTable is), the 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 NSView's autoresizing mechanism.

You create a GSTable instance with a certain number of rows and columns.  The 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 GSTable, by calling a method of the family -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 GSTable is zero; each time you put a view in the GSTable, the GSTable recomputes sizes and as a result resizes itself so that it exactly fits the views it contains. You should not force a GSTable in a size different from the one it has automatically computed.  The only acceptable, reasonable and meaningful way of resizing a GSTable is through the appropriate -resizeWithOldSuperviewSize: message when the 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 GSTable is free or filled with a view and its margins.

The 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 -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 -sizeToFit.

When the GSTable receives a -resizeWithOldSuperviewSize: message, it automatically rearranges the views it contains:

  * If the new width or height is equal or less than the table's minimum width or height, the GSTable simply arranges its views in the initial position.  In other words, the GSTable refuse to resize below its minimum width or height.  If you do that, part of the GSTable is clipped.

  * 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 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 NSViewMinXMargin | NSViewMaxXMargin | 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 -setAutoresizingMask: method of the NSView class.

You may find practical examples of the use of the GSTable class in the Testing directory of the source code of the GNUstep Library.

Advanced Description of GSTable
-------------------------------

We call any view which is added to the GSTable a prisoner. The purpose of the GSTable is to effectively manage its prisoners.  To do so, the GSTable creates a special view, called a jail, for each prisoner.  The jails are subviews of the GSTable; each prisoner, when added to the GSTable, is made a subview of its jail.  The 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 -frame message, the frame of the jail (and not the frame of the 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 GSTable manages directly the jails, each prisoner is managed together with its margins.  When the jail is resized, the prisoner receives a -resizeWithOldSuperviewSize:, which makes it resize itself and its margins in the new jail size, according to its autoresizingMask.

GSTable Method Description
--------------------------

Initializing a GSTable
......................

-(id) initWithNumberOfRows: (int)rows

   numberOfColumns: (int)columns

Initialize a GSTable with columns columns and rows rows.  If columns or rows is negative or null, a warning is issued and a default of 2 is used instead.

-(id) init

Initialize a GSTable with 2 columns and 2 rows.

Putting Views in a GSTable
..........................

Use these methods to put views in the GSTable:

-(void) putView: (NSView *)aView

    atRow: (int)row

    column: (int)column

Put aView in the GSTable, in the specified row and column.  Zero (0) margins are used.  If the column column (or the row row) is not enough big to fully display 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.

-(void) putView: (NSView *)aView

    atRow: (int)row

    column: (int)column

    withMargins: (float)margins

Put aView in the GSTable, using margins as margin in all directions: left, right, top, bottom.

-(void) putView: (NSView *)aView

    atRow: (int)row

    column: (int)column

    withXMargins: (float)xMargins

    yMargins: (float)yMargins

Put aView in the GSTable, using xMargins as the left and right margins, and yMargins as the top and bottom margins.

-(void) putView: (NSView *)aView

    atRow: (int)row

    column: (int)column

    withMinXMargin: (float)minXMargin

    maxXMargin: (float)maxXMargin

    minYMargin: (float)minYMargin

    maxYMargin: (float)maxYMargin

Put aView in the 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:

minXMargin
     Left Margin

maxXMargin
     Right Margin

minYMargin
     Lower Margin (Upper if view is flipped)

maxYMargin
     Upper Margin (Lower if view is flipped)

Setting Borders
...............

-(void) setBorder: (float)aBorder

Set the GSTable up, bottom, left and right borders to the same value aBorder.  The GSTable is immediately updated.  If 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 GSTable coordinate system.

-(void) setXBorder: (float)aBorder

Set the GSTable left and right borders to aBorder.  If aBorder is negative, the border is reset to zero.  The GSTable is immediately updated.

-(void) setYBorder: (float)aBorder

Same as setXBorder: but set the up and bottom borders.

-(void) setMinXBorder: (float)aBorder

Same as setXBorder: but set only the left border.

-(void) setMaxXBorder: (float)aBorder

Same as setXBorder: but set only the right border.

-(void) setMinYBorder: (float)aBorder

Same as setXBorder: but set only the lower border (upper if the GSTable is flipped).

-(void) setMaxYBorder: (float)aBorder

Same as setXBorder: but set only the upper border (lower if the GSTable is flipped).

Minimum Size.
.............

-(NSSize) 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.

Resizing.
.........

-(void) 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.

Setting Row and Column Expand Flag
..................................

When the 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 GSTable.  Note that when the GSTable is first created, all its columns and rows have by default resizing enabled.

-(void) setXResizingEnabled: (BOOL)aFlag

    forColumn: (int)aColumn

Enable/disable X Resizing for the column aColumn according to aFlag.  Note: at present, enabling/disabling X resizing after the table has been put in the view hierarchy is not supported.

-(void) setYResizingEnabled: (BOOL)aFlag

    forRow: (int)aRow

Enable/disable Y Resizing for the row aRow according to aFlag.  Note: at present, enabling/disabling Y resizing after the table has been put in the view hierarchy is not supported.

-(BOOL) isXResizingEnabledForColumn: (int)aColumn

Return whether X resizing is enabled for the column aColumn.

-(BOOL) isYResizingEnabledForRow: (int)aRow

Return whether Y resizing is enabled for the row aRow.

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 GSTable with the right number of rows and columns from the beginning.

-(void) addRow

Add a row to the GSTable.  The row is added void, with zero height and Y Resizing enabled.

-(void)  addColumn

Add a column to the GSTable.  The column is added void, with zero width and X Resizing enabled.

Getting Row and Column Number
.............................

-(int) numberOfRows

Return the number of rows in the GSTable.

-(int) numberOfColumns

Return the number of columns in the GSTable.

GSVbox Reference
================

GSVbox Class
------------

     Inherits from: GSTable: NSView: NSResponder: NSObject

     Conforms to:  NSCoding (from NSResponder),
     NSObject (from NSObject)

     Declared in: AppKit/GSVbox.h

GSVbox is a GNUstep GUI extension to the OpenStep specification.

GSVbox Overview
---------------

A GSVbox is completely analogue to a 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:

-(id) init

-(void) setBorder: (float)aBorder

-(void) setXBorder: (float)aBorder

-(void) setYBorder: (float)aBorder

-(void) setMinXBorder: (float)aBorder

-(void) setMaxXBorder: (float)aBorder

-(void) setMinYBorder: (float)aBorder

-(void) setMaxYBorder: (float)aBorder

-(void) addView: (NSView *)aView

-(void) addView: (NSView *)aView

    enablingYResizing: (BOOL)aFlag

-(void) addView: (NSView *)aView

    withMinYMargin: (float)aMargin

-(void) addView: (NSView *)aView

    enablingYResizing: (BOOL)aFlag

    withMinYMargin: (float)aMargin

-(void) addSeparator

-(void) addSeparatorWithMinYMargin: (float)aMargin

-(void) setDefaultMinYMargin: (float)aMargin

-(NSSize) minimumSize

-(void) sizeToFit

-(int) numberOfView

See the documentation for the corresponding GSHbox class methods for more information.

Tools Included with gstep-gui.
******************************

Implementation Details
**********************

Following are some implementation details of the GUI library. These will mostly be of interest to developers of the GUI library itself.

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 -

     NSArray *GSGetDragTypes(NSView *aView);

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 -

     - (NSCountedSet*) _dragTypesForWindow: (int)winNum;

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.

     - (BOOL) _addDragTypes: (NSArray*)types toWindow: (int)winNum;
     - (BOOL) _removeDragTypes: (NSArray*)types fromWindow: (int)winNum;

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

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 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:

~/GNUstep/Services/.GNUstepAppList
     Cached information about applications and file extensions.

~/GNUstep/Services/.GNUstepExtPrefs
     User preferences for which apps/icons should be used for each file extension.

~/GNUstep/Services/.GNUstepServices
     Cache of services provides by apps and services daemons

~/GNUstep/Services/.GNUstepDisabled
     User settings to determine which services should not appear in the services menu.

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:

     {
       NSExecutable = "xv";
       NSIcon = "xv.tiff";
       NSTypes = (
         {
           NSIcon = "tiff.tiff";
           NSUnixExtensions = ( tiff, tif );
         },
         {
           NSIcon = "xbm.tiff";
           NSUnixExtensions = ( xbm );
         }
       );
     }

Special Setup Instructions.
***************************

Keyboard Modifiers
==================

This section applies only to the xgps and the xdps backend.

Default Settings
----------------

The OPENstep specification requires 3 main different keyboard modifiers: CONTROL, COMMAND and ALTERNATE.

  * 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 Command - q.

  * CONTROL and ALTERNATE are two additional modifiers. A typical use of ALTERNATE is to scroll by pages rather than by lines; you have to press ALTERNATE while acting on a scrollbar with the mouse.

By default, GNUstep uses Control_L (left Ctrl) and Control_R (right Ctrl) as CONTROL, Alt_L (left alt) as COMMAND, and Alt_R (right alt, sometimes called AltGr) as ALTERNATE.

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.

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 CONTROL, COMMAND and 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 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 CONTROL, COMMAND and 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 CONTROL you have to set GSFirstControlKey and GSSecondControlKey; and similarly for the other keys:

CONTROL
     GSFirstControlKey GSSecondControlKey

COMMAND
     GSFirstCommandKey GSSecondCommandKey

ALTERNATE
     GSFirstAlternateKey GSSecondAlternateKey

Valid values are all the standard strings for X keys. To disable completely a key, use NoSymbol as preference.

Each value which you do not explicity set is substituted with its default value.  The default values are:

GSFirstControlKey
     Control_L

GSSecondControlKey
     Control_R

GSFirstCommandKey
     Alt_L

GSSecondCommandKey
     NoSymbol

GSFirstAlternateKey
     Alt_R

GSSecondAlternateKey
     NoSymbol

What could go wrong is for example that you don't have an Alt_L key.  With the default settings, you will not be able to enter the COMMAND key (which is quite an important key). What you can do in this case is to use Control_R as COMMAND, giving the following commands (from the command line):

     defaults write NSGlobalDomain GSFirstCommandKey Control_R
     defaults write NSGlobalDomain GSSecondControlKey NoSymbol

These commands write in the GNUstep user database; the information will be used every time you start a GNUstep application.

The first line sets GSFirstCommandKey to Control_R, which makes Control_R to be read as COMMAND.

The second line disables the second control key, which would otherwise be bound to Control_R by default. If you omit it, Control_R will be used at the same time as COMMAND and as CONTROL, which is not very useful.

To delete these preferences and restore the defaults, use

     defaults delete NSGlobalDomain GSFirstCommandKey
     defaults delete NSGlobalDomain GSSecondControlKey

To get a list of currently set defaults, you may use

     defaults read

The list might be very long; you may want to extract only setting for the GSFirstCommandKey, for example:

     defaults read | grep GSFirstCommandKey

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 xmodmap or 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.

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.

Contributing
************

Contributing code is not difficult. Here are some general guidelines:

  * 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.

  * 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.

  * 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.

  * Assistance in providing documentation, test files, and debugging support is strongly encouraged.

Extensions, comments, and suggested modifications of existing libgnustep-gui features are also very welcome.