1 /*
2    GSHbox.h
3 
4    The GSHbox class (a GNU extension)
5 
6    Copyright (C) 1999 Free Software Foundation, Inc.
7 
8    Author:  Nicola Pero <n.pero@mi.flashnet.it>
9    Date: 1999
10 
11    This file is part of the GNUstep GUI Library.
12 
13    This library is free software; you can redistribute it and/or
14    modify it under the terms of the GNU Lesser General Public
15    License as published by the Free Software Foundation; either
16    version 2 of the License, or (at your option) any later version.
17 
18    This library is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
21    Lesser General Public License for more details.
22 
23    You should have received a copy of the GNU Lesser General Public
24    License along with this library; see the file COPYING.LIB.
25    If not, see <http://www.gnu.org/licenses/> or write to the
26    Free Software Foundation, 51 Franklin Street, Fifth Floor,
27    Boston, MA 02110-1301, USA.
28 */
29 
30 #ifndef _GNUstep_H_GSHbox
31 #define _GNUstep_H_GSHbox
32 
33 #import "GSTable.h"
34 
35 /**
36   <unit>
37   <heading>GSHbox</heading>
38 
39   <p>
40   GSHbox inherits from GSTable the autosizing/autoresizing engine.
41   The only real difference between a GSHbox and a GSTable with 1 row
42   is that the GSHbox has a much simpler, easier and friendlier API.
43   </p>
44   <p>
45   You shouldn't use GSTable methods with GSHbox (exception: methods
46   explicitly quoted in comments to this file as 'inherited from GSTable').
47   If you need to do that, you should be using GSTable instead.
48   </p>
49   <p>
50   A GSHbox is an invisible view (a logical device) which can
51   contain some views.  The GSHbox controls the position and sizes
52   of these views so that they are lined up in a row.
53   </p>
54   <p>
55   To initialize a GSHbox, you should always use -init
56   method.  Don't use GSTable methods.  The correct way to start
57   using a new GSHbox is simply:
58   </p>
59   <example>
60   hbox = [GSHbox new];
61   </example>
62   <p>
63   (well, of course, autoreleasing it if necessary).  You add a view to a
64   GSHbox using the method -addView: and its variants.  The
65   views you add to a GSHbox are placed by the GSHbox in its
66   subview hierarchy, and moved (and/or resized in the vertical direction)
67   so that they are positioned one after the other, from left to right, in
68   a row.  Before adding views to a box, you should resize them to the
69   least comfortable size you want them to have.  The GSHbox
70   considers this size as the minimum size your view should ever have, and
71   never resizes your view below this size.
72   </p>
73   <p>
74   The initial size of the GSHbox is zero; each time you add a view
75   in the GSHbox, the GSHbox resizes itself to fit the new
76   contents.  Usually, you simply add objects to the GSHbox, and let
77   it compute its size (this is the minimum size); you may get this
78   resulting size by
79   </p>
80   <example>
81   size = [yourHBox size];
82   </example>
83   <p>
84   for example, if the GSHbox is to be used as the content view of a window,
85   you may create the window exactly with this size.
86   </p>
87   <p>
88   You should never force a GSHbox in a size different from the one
89   it has automatically computed.  It sounds quite pointless anyway.  The
90   only correct (and meaningful) way to resize a GSHbox is through
91   -resizeWithOldSuperviewSize: messages (in the view hierarchy).
92   In other words, after you place your box in the view hierarchy, then you
93   may resize the superview and (if the superview has autoresizing of
94   subviews enabled) your box is resized automatically accordingly.
95   </p>
96   <p>
97   By default, there is no space between the added views.  By using the method
98   -addView:withMinXMargin: you may tell the GSHbox to insert
99   some space (a <var>margin</var>) between the view you are adding and the
100   previous one (the one at its left).
101   </p>
102   <p>
103   If what you want is space around the GSHbox, and not between
104   views in the GSHbox, you don't want a margin but a <var>border</var>;
105   you should then use -setBorder:, which will add an equal amount
106   of space on all the sides of the box.  You can also set a different
107   border on each side (see -setMinXBorder: and similar methods).
108   </p>
109   <p>
110   A useful feature of GSHbox is that it supports <var>separators</var>.
111   This facility is not directly available in GSTable (to add
112   separators to a GSTable you need to create and handle them
113   yourself).  A GSHbox separator is a vertical groove line, used to
114   mark the separation between different elements of a box.  To add a
115   separator, simply invoke the method -addSeparator.  The separator
116   is put at the right of the last added view.
117   </p>
118   <p>
119   To use GSHbox proficiently, it is crucial to set correctly the
120   autoresizing mask of each view before adding it to the GSHbox.
121   </p>
122   <p>
123   The GSHbox treats each view and its margins as a whole (see the
124   GSTable class description for more information).
125   </p>
126   <p>
127   When the GSHbox is resized in the vertical direction (as a
128   consequence of user intervertion, for example), what happens is:
129   </p>
130   <list>
131   <item> if the new height is less than the minimum height of the GSHbox
132   (computed as the maximum of the minimum height of the added views), it
133   simply resizes all the added views to this minimum height; part of them
134   are clipped then.
135   </item>
136   <item> if the new height is greater than the GSHbox's minimum height,
137   the GSHbox resizes all the added views to the new height.  This
138   is done through the standard superview-subview resizing mechanism, so
139   that, by setting the autoresizingMask of each view that you add,
140   you are able to control exactly how the resizing effects each view and
141   its margins.
142   </item>
143   </list>
144   <p>
145   When the GSHbox is resized in the horizontal direction, its
146   behaviour is as follows:
147   </p>
148   <list>
149   <item> If the new width is less than
150   the minimum width, all the added views are sized to minimum width; part
151   of them is clipped then.
152   </item>
153   <item> If the new width is greater than
154   the minimum width, some of the views are resized.  You may decide which
155   views you want to be resized and which not; to disable resizing of a
156   certain view in the horizontal direction, you should specify a NO
157   value to the option <code>enablingXResizing</code> when you add the view to
158   the box.  Views with X Resizing Not Enabled are always kept in their
159   minimum width (the original one), and never resized.  If nothing is
160   specified, a default of YES for <code>enablingXResizing</code> is
161   understood.  So, when the new width is greater than the minimum width,
162   the excess width is equally divided between the view with X Resizing
163   Enabled.  The actual resizing is done through the usual
164   superview-subview resizing mechanism, so that again you may influence
165   the way the resizing affects each view by setting the autoresizing mask
166   of each view.
167   </item>
168   </list>
169 
170   </unit>
171 */
172 @interface GSHbox: GSTable
173 {
174   BOOL _haveViews;
175   float _defaultMinXMargin;
176 }
177 //
178 // Initizialing.
179 //
180 /** Always use init for GSHbox: other methods don't make sense.
181  Don't used GSTable methods.  You do not need to specify
182  the number of views you plan to put in the box
183  when you initialize it.
184 */
185 -(id) init;
186 
187 //
188 //  Adding a View.
189 //
190 /** See  -addView:enablingXResizing:withMinXMargin: */
191 -(void) addView: (NSView *)aView;
192 
193 /** See  -addView:enablingXResizing:withMinXMargin: */
194 -(void) addView: (NSView *)aView
195 enablingXResizing: (BOOL)aFlag;
196 
197 /** See  -addView:enablingXResizing:withMinXMargin: */
198 -(void) addView: (NSView *)aView
199  withMinXMargin: (float)aMargin;
200 
201 /** <p> Pack views in the GSHbox.
202   Don't use the corresponding methods of GSTable, which are far more general
203   and far more complicate.  If you need to do that, use GSTable instead.
204   </p>
205   <p>
206   Add a view to the box, enabling X Resizing only if flag is
207   YES, and a MinXMargin aMargin.  If aFlag is
208   YES the [view and its margins] should be resized in the
209   horizontal direction when the GSHbox is resized in the horizontal
210   direction.  If aFlag is NO the view is never X-resized and
211   always left in its original width.  The default is YES.
212   </p>
213   <p>
214   The min X margin is used to separate the view from the preceding one.
215   The first view added to the box has no min X margin; if you try setting
216   one for it, it is ignored (zero is used instead).
217   </p>
218   <p>
219   When views are added to the GSHbox, it might happen that some of
220   the added views have a greater height than others.  When this happens,
221   the GSHbox resizes all the views to the highest height.  As
222   usual, each view is resized with its margins; the effect of the resizing
223   on each view is determined by the autoresizing mask of the view.  The
224   classical options are
225   </p>
226   <deflist>
227   <term> (NSViewMinYMargin | NSViewMaxYMargin) </term>
228   <desc>Center the view vertically</desc>
229   <term> NSViewMinYMargin </term>
230   <desc>Flush the view up (down if the GSHbox is flipped)</desc>
231   <term> NSViewMaxYMargin  </term>
232   <desc>Flush the view down (up if the GSHbox is flipped)</desc>
233   <term> NSViewHeightSizable </term>
234   <desc>Expand the view to the whole height</desc>
235   </deflist>
236   <p>
237   (you may need to OR these masks with the mask you use in the
238   horizontal direction, if you use any).
239   </p>
240   <p>
241   With a GSHbox, only one margin is set when you add views to the GSHbox:
242   the margin between each view and the preceding one.
243   Exception: the first view is special, and has no margin set (it has no
244   preceding view to be separated from).
245   Space above or below the view may result if the view is shorter,
246   in the vertical direction, than the other views in the GSHbox;
247   in that case the view is resized to fit vertically,
248   according to its autoresizingMask.
249   By changing the autoresizingMask you may decide whether the space
250   should go to the view or to its vertical margins; this for example
251   lets you center vertically or flush up/down your view.
252   </p>
253 */
254 -(void) addView: (NSView *)aView
255   enablingXResizing: (BOOL)aFlag
256   withMinXMargin: (float)aMargin;
257 
258 //
259 // Adding a Separator.
260 //
261 /** Add a separator with the default MinXMargin. */
262 -(void) addSeparator;
263 
264 /** Add a separator (a vertical groove line encompassing all the
265 height of the GSHbox) to the GSHbox, inserting a margin aMargin
266 between the separator and the last added view.
267 */
268 -(void) addSeparatorWithMinXMargin: (float)aMargin;
269 
270 //
271 //  Setting Margins.
272 //
273 
274 /** Use only the following method to set a default margin.
275  The default margin set with the following method will be used
276  for all the views added after.
277  (Exception: the first view put in the box has no margins at all)
278  It will not affect already added views.
279  In a GSHbox, only one margin is used, the one between each view
280  and the preceding one.  If what you want is space around the GSHbox,
281  you don't want a margin but a border; use setBorder:
282  (see GSTable, "Setting Border").
283  If you need more complicated margins/borders, use GSTable.
284 */
285 -(void) setDefaultMinXMargin: (float)aMargin;
286 
287 //
288 // Getting Number of Views
289 //
290 
291 /** Return the number of views in the GSHbox (separators included).  */
292 -(int) numberOfViews;
293 @end
294 
295 #endif /* _GNUstep_H_GSHbox */
296