libyui
3.0.10
|
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