libyui  3.0.10
/usr/src/RPM/BUILD/libyui-3.0.10/src/YButtonBox.h
00001 /*
00002   Copyright (C) 2000-2012 Novell, Inc
00003   This library is free software; you can redistribute it and/or modify
00004   it under the terms of the GNU Lesser General Public License as
00005   published by the Free Software Foundation; either version 2.1 of the
00006   License, or (at your option) version 3.0 of the License. This library
00007   is distributed in the hope that it will be useful, but WITHOUT ANY
00008   WARRANTY; without even the implied warranty of MERCHANTABILITY or 
00009   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
00010   License for more details. You should have received a copy of the GNU
00011   Lesser General Public License along with this library; if not, write
00012   to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
00013   Floor, Boston, MA 02110-1301 USA
00014 */
00015 
00016 
00017 /*-/
00018 
00019   File:         YButtonBox.h
00020 
00021   Author:       Stefan Hundhammer <sh@suse.de>
00022 
00023 /-*/
00024 
00025 #ifndef YButtonBox_h
00026 #define YButtonBox_h
00027 
00028 #include <vector>
00029 
00030 #include "YWidget.h"
00031 #include "YPushButton.h"
00032 
00033 class YButtonBoxPrivate;
00034 class YPushButton;
00035 
00036 
00037 /**
00038  * Helper class: Layout policy for YButtonBox widgets.
00039  * This is used in the default YButtonBox::doLayout() method.
00040  **/
00041 struct YButtonBoxLayoutPolicy
00042 {
00043     YButtonBoxLayoutPolicy()
00044         : buttonOrder( YKDEButtonOrder )
00045         , equalSizeButtons( false )
00046         , addExcessSpaceToHelpButtonExtraMargin( false )
00047     {
00048         alignment[ YD_HORIZ ] = YAlignCenter;
00049         alignment[ YD_VERT  ] = YAlignBegin;    // Align top
00050     }
00051 
00052     YButtonOrder        buttonOrder;      // YKDEButtonOrder / YGnomeButtonOrder
00053     bool                equalSizeButtons; // Make all buttons the same size?
00054     bool                addExcessSpaceToHelpButtonExtraMargin;
00055 
00056     // Alignment for the YButtonBox itself
00057     YAlignmentType      alignment[ YUIAllDimensions ];
00058 };
00059 
00060 
00061 /**
00062  * Helper class: Margins for YButtonBox widgets.
00063  * All sizes are in UI-dependent units, i.e. in pixels.
00064  **/
00065 struct YButtonBoxMargins
00066 {
00067     YButtonBoxMargins()
00068         : left( 0 )
00069         , right( 0 )
00070         , top( 0 )
00071         , bottom( 0 )
00072         , spacing( 0 )
00073         , helpButtonExtraSpacing( 0 )
00074         {}
00075 
00076     int left;                   // Left of the leftmost button
00077     int right;                  // Right of the rightmost button
00078     int top;                    // Above the hightest button
00079     int bottom;                 // Below the hightest button
00080 
00081     int spacing;                // Between buttons
00082     int helpButtonExtraSpacing; // Between [Help] and the next button
00083 };                              // (additionally to "spacing"!)
00084 
00085 
00086 /**
00087  * Container widget for dialog buttons that abstracts the button order
00088  * depending on the desktop environment.
00089  *
00090  * KDE and Windows arrange dialog buttons like this:
00091  *
00092  *     [OK] [Apply] [Cancel] [Custom1] [Custom2] ... [Help]
00093  *
00094  *     [Continue] [Cancel]
00095  *
00096  *     [Yes] [No]
00097  *
00098  *
00099  * GNOME and MacOS arrange them like this:
00100  *
00101  *     [Help] [Custom1] [Custom2] ... [Apply] [Cancel] [OK]
00102  *
00103  *     [Cancel] [Continue]
00104  *
00105  *     [No] [Yes]
00106  *
00107  *
00108  * This class provides the abstraction to use whatever layout is more
00109  * appropriate in the current environment. The application creates the buttons
00110  * as child widgets of a YButtonBox (rather than a YHBox) and leaves the button
00111  * order to the YButtonBox.
00112  *
00113  * Each of the standard buttons ([OK], [Apply], [Cancel], [Help]) needs to have
00114  * a button role properly assigned.
00115  *
00116  * If set up properly (see YApplication::setDefaultFunctionKey()), known button
00117  * labels will be assigned an appropriate role:
00118  *
00119  *     [OK]                     F10
00120  *     [Continue] -> [OK]       F10
00121  *     [Yes]      -> [OK]       F10
00122  *     [Accept]   -> [OK]       F10
00123  *     [Next]     -> [OK]       F10
00124  *
00125  *     [Cancel]                 F9
00126  *     [No]       -> [Cancel]   F9
00127  *
00128  *     [Help]                   F1
00129  *
00130  * Buttons with nonstandard labels that act in such a role need to be
00131  * explicitly assigned that role:
00132  *
00133  *     [Print ] [Cancel] [Help]
00134  *     [Delete] [Cancel] [Help]
00135  *
00136  * Those [Print] or [Delete] buttons act as [OK] buttons (the "yes, do it"
00137  * action of that dialog). Call YPushButton::setButtonRole( YOkButton )
00138  * explicitly for them.
00139  *
00140  *
00141  * YButtonBox widgets only accept YPushButton child widgets. Otherwise an
00142  * exception is thrown.
00143  *
00144  * If there is more than one button, one of the child buttons needs to have the
00145  * [OK] role, and another needs to have the [Cancel] role. Otherwise an
00146  * exception is thrown.
00147  **/
00148 class YButtonBox : public YWidget
00149 {
00150     friend class YButtonBoxPrivate;
00151 
00152 protected:
00153     /**
00154      * Constructor.
00155      **/
00156     YButtonBox( YWidget * parent );
00157 
00158 public:
00159 
00160     /**
00161      * Destructor.
00162      **/
00163     virtual ~YButtonBox();
00164 
00165     /**
00166      * Return a descriptive name of this widget class for logging,
00167      * debugging etc.
00168      **/
00169     virtual const char * widgetClass() const { return "YButtonBox"; }
00170 
00171     /**
00172      * Set the button policy for all future YButtonBox widgets:
00173      * Button order, alignment if there is any excess space, whether or not to
00174      * give all buttons the same size.
00175      *
00176      * You might want to use one of the predefined static methods:
00177      * YButtonBox::kdeLayoutPolicy(), YButtonBox::gnomeLayoutPolicy().
00178      *
00179      * The default doLayout() method uses those values.
00180      *
00181      * Notice that there is intentionally no way to set this differently for
00182      * each individual YButtonBox: This would defeat the purpose of consistency
00183      * (with the desktop environment this application is running in), which is
00184      * the reason for having this widget class.
00185      **/
00186     static void setLayoutPolicy( const YButtonBoxLayoutPolicy & layoutPolicy );
00187 
00188     /**
00189      * Return the layout policy.
00190      **/
00191     static YButtonBoxLayoutPolicy layoutPolicy();
00192 
00193     /**
00194      * Predefined layout policy for KDE-like behaviour.
00195      **/
00196     static YButtonBoxLayoutPolicy kdeLayoutPolicy();
00197 
00198     /**
00199      * Predefined layout policy for GNOME-like behaviour.
00200      **/
00201     static YButtonBoxLayoutPolicy gnomeLayoutPolicy();
00202 
00203     /**
00204      * Set the default margins for all future YButtonBox widgets.
00205      **/
00206     static void setDefaultMargins( const YButtonBoxMargins & margins );
00207 
00208     /**
00209      * Return the default margins for all future YButtonBox widgets.
00210      **/
00211     static YButtonBoxMargins defaultMargins();
00212 
00213     /**
00214      * Set the margins for this YButtonBox.
00215      *
00216      * Derived classes are free to reimplement this, but they should call this
00217      * base class method in the new method.
00218      **/
00219     virtual void setMargins( const YButtonBoxMargins & margins );
00220 
00221     /**
00222      * Return the margins of this YButtonBox.
00223      *
00224      * Notice that those are only the desired margins; if there is not enough
00225      * space, margins and spacings will be reduced before buttons are cut off.
00226      **/
00227     YButtonBoxMargins margins() const;
00228 
00229     /**
00230      * Lay out the button box and its children (its buttons). This is where the
00231      * button order is implemented.
00232      *
00233      * This method is called by the default setSize() method. It uses
00234      * YButtonBox::layoutPolicy() and the specified margins (defaultMargins
00235      * unless changed with setMargins() ). It moves the buttons to their
00236      * position with moveChild().
00237      *
00238      * This all should work reasonably in all cases (Qt-UI with KDE button
00239      * order, Gtk-UI with Gnome button order, NCurses-UI with KDE button
00240      * order).
00241      *
00242      * Still, derived classes can reimplement this. It does not make very much
00243      * sense to call this default method in a new implementation.
00244      **/
00245     virtual void doLayout( int width, int height );
00246 
00247     /**
00248      * Search the child widgets for the first button with the specified role.
00249      * Return the button or 0 if there is no button with that role.
00250      **/
00251     YPushButton * findButton( YButtonRole role );
00252 
00253     /**
00254      * Sanity check: Check if all child widgets have the correct widget class
00255      * and if the button roles are assigned correctly.
00256      *
00257      * A YButtonBox with more than one button is required to have one YOKButton
00258      * and ony YCancelButton. Neither button role may be assigned more than
00259      * once.
00260      *
00261      * This method may throw exceptions:
00262      * - YUIButtonRoleMismatchException
00263      * - YUIInvalidChildException       (wrong widget class)
00264      *
00265      * This cannot be done as child widgets are inserted since this is done
00266      * from the child widgets' constructors, so virtual methods or dynamic_cast
00267      * don't work at that point.
00268      *
00269      * This is called in the default setSize() method (just before doLayout()),
00270      * so any of the above errors are caught only at that time. Applications
00271      * are free to call this before that time to make error handling more
00272      * transparent.
00273      **/
00274     void sanityCheck();
00275 
00276     /**
00277      * Relax the sanity check done in sanityCheck(): Do not enforce that there
00278      * has to be a YOKButton and a YCancelButton if there is more than one
00279      * button.
00280      *
00281      * In very rare cases, it might be neccessary to have a less stringent
00282      * sanity check: There are some very few legitimate cases for having a
00283      * YButtonBox with multiple buttons, yet without a YCancelButton.
00284      *
00285      * Examples:
00286      *
00287      *     ...message...
00288      *      <Countdown>
00289      *      [OK] [Stop]
00290      *
00291      *     ...message...
00292      *     [OK] [Details]
00293      *
00294      * In those cases, it makes sense to relax the sanity check.
00295      **/
00296     void setSanityCheckRelaxed( bool relax = true );
00297 
00298     /**
00299      * Return 'true' if sanity checks are currently relaxed, 'false' if not.
00300      **/
00301     bool sanityCheckRelaxed() const;
00302 
00303     /**
00304      * Preferred width of the widget.
00305      *
00306      * Reimplemented from YWidget. This default method returns the sum of
00307      * the the widths of all child widgets plus the left and right margins plus
00308      * the spacings.
00309      *
00310      * Derived classes can reimplement this method. It does not make very much
00311      * sense to call this base class method in a new implementation.
00312      **/
00313     virtual int preferredWidth();
00314 
00315     /**
00316      * Preferred height of the widget.
00317      *
00318      * Reimplemented from YWidget. This default method returns the height of
00319      * the highest child plus the top and bottom margins.
00320      *
00321      * Derived classes can reimplement this method. It does not make very much
00322      * sense to call this base class method in a new implementation.
00323      **/
00324     virtual int preferredHeight();
00325 
00326     /**
00327      * Sets the size of the YButtonBox.
00328      *
00329      * Derived classes can reimplement this, but this base class method should
00330      * be called in the reimplemented function.
00331      *
00332      * Reimplemented from YWidget.
00333      **/
00334     virtual void setSize( int newWidth, int newHeight );
00335 
00336     /**
00337      * Returns the stretchability of the YButtonBox. YButtonBox widgets are
00338      * horizontally stretchable by default. How any excess space is used is
00339      * specified in the layout policy.
00340      *
00341      * Reimplemented from YWidget.
00342      **/
00343     virtual bool stretchable( YUIDimension dimension ) const;
00344 
00345 
00346 protected:
00347 
00348     /**
00349      * Return the button children sorted (left to right) by the current button
00350      * order (from the layout policy).
00351      *
00352      * This default implementation handles KDE and Gnome button orders. It is
00353      * used in the default doLayout() method.
00354      *
00355      * This may throw exceptions if there are non-button children or if there
00356      * are multiple buttons with any of the standard button roles (except
00357      * YCustomButton, of course).
00358      **/
00359     virtual std::vector<YPushButton *> buttonsByButtonOrder();
00360 
00361     /**
00362      * Return the (preferred) size of the biggest child widget in the specified
00363      * dimension.
00364      **/
00365     int maxChildSize( YUIDimension dim ) const;
00366 
00367     /**
00368      * Return the sum of the (preferred) widths of all child widgets.
00369      **/
00370     int totalChildrenWidth() const;
00371 
00372     /**
00373      * Move a child to a new position. This is used in doLayout().
00374      *
00375      * Derived classes are required to implement this.
00376      **/
00377     virtual void moveChild( YWidget * child, int newX, int newY ) = 0;
00378 
00379     /**
00380      * Calculate the preferred with with or without trying to enforce buttons
00381      * of equal size.
00382      **/
00383     int preferredWidth( bool equalSizeButtons );
00384 
00385 
00386 private:
00387 
00388     ImplPtr<YButtonBoxPrivate> priv;
00389 
00390     static YButtonBoxLayoutPolicy       _layoutPolicy;
00391     static YButtonBoxMargins            _defaultMargins;
00392 };
00393 
00394 
00395 #endif // YButtonBox_h
 All Classes Functions Variables Enumerations Friends