1 // -*- mode: c++ -*- 2 // 3 // This file is part of libyacurs. 4 // Copyright (C) 2013 Rafael Ostertag 5 // 6 // This program is free software: you can redistribute it and/or 7 // modify it under the terms of the GNU General Public License as 8 // published by the Free Software Foundation, either version 3 of the 9 // License, or (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, but 12 // WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 // General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program. If not, see 18 // <http://www.gnu.org/licenses/>. 19 // 20 // 21 // $Id$ 22 23 #ifndef PACK_H 24 #define PACK_H 1 25 26 #include <list> 27 28 #include "area.h" 29 #include "widgetbase.h" 30 31 namespace YACURS { 32 /** 33 * A container widget for stacking widgets horizontally or vertically. 34 * 35 * A pack is a list of widgets, that are either horizontally, or 36 * vertically stacked and displayed. 37 * 38 * The pack will calculate the size needed for displaying the widgets 39 * horizontally, vertically. This should happen on realize() which is 40 * required to be implemented in derived classes. 41 * 42 * @warning If a Pack is destroyed before its associated Widgets, the 43 * Widgets will have a __parent pointer that is invalid. 44 * 45 * @see VPack 46 * @see HPack 47 */ 48 class Pack : public WidgetBase { 49 private: 50 /** 51 * The Size of the Pack. 52 * 53 * This will be set by calling size_available(). 54 * 55 * @internal 56 * 57 * the only reason for maintaining that field 58 * is, so that we can reset the size when reset_size() is 59 * called and return Size::zero() on subsequent calls to 60 * Pack::size(). Pack::size() may even choose to use a 61 * different size (@sa Pack::size()). 62 */ 63 Size _size; 64 65 /** 66 * When hinting is enabled (@c true) Pack::size_hint() queries 67 * associated Widgets for hints and returns a hint based on 68 * the result. When disabled (@c false) Pack::size_hint() 69 * always returns Size::zero(). 70 * 71 * Default @c true. 72 */ 73 bool _hinting; 74 75 /** 76 * Indicates whether or not the Pack should behave as 77 * dynamically sized Widget. 78 * 79 * If @c true, a call to Pack::size() does NOT invoke call 80 * calc_size_non_dynamic(), which in turn returns Size != 81 * Size::zero() if all associated Widgets are non-dynamic. 82 * 83 * If @c false Pack::size() calls calc_size_non_dynamic() and 84 * may return that result. 85 * 86 * Default @c false. 87 */ 88 bool _always_dynamic; 89 90 /** 91 * Call curses_window() on all associated Widgets. 92 */ 93 void set_all_curses_window(); 94 95 /** 96 * Call focusgroup_id() on all associated Widgets. 97 */ 98 void set_all_focusgroup_id(); 99 100 /** 101 * Refresh all associated Widgets. 102 * 103 * @param i immediate flag. @sa Realizeable::refresh(). 104 */ 105 void refresh_all_widgets(bool i); 106 107 /** 108 * Calculate size required. 109 * 110 * Calculate the size required. Returns a Size not equal 111 * to Size::zero() only if there are no dynamically sized 112 * Widgets associated. 113 * 114 * @internal 115 * 116 * the idea is to use this function in size(), so it 117 * should return a Size != Size::zero() only if we can 118 * determine the size of all Widgets definitely, without 119 * calculating the size for dynamically sized Widgets. In 120 * other words, the Pack appears non-dynamically only if 121 * there are no dynamically sized Widgets associated. 122 */ 123 virtual Size calc_size_non_dynamic() const = 0; 124 125 void take_over(WidgetBase* w); 126 127 protected: 128 /** 129 * List of all Widgets associated with the Pack. 130 */ 131 std::list<WidgetBase*> widget_list; 132 133 void unrealize(); 134 135 public: 136 Pack(); 137 138 Pack& operator=(const Pack&) = delete; 139 Pack(const Pack&) = delete; 140 Pack& operator=(Pack&&) = delete; 141 Pack(Pack&&) = delete; 142 143 virtual ~Pack(); 144 145 std::list<WidgetBase*>::size_type widgets() const; 146 147 /** 148 * Add a widget to the Pack. The widget will be added in front 149 * of any other widget. 150 * 151 * @important Widgets can only be added before the Pack is 152 * realized. It is not possible to add a Widget after the pack 153 * has been realized. Attempt to do so will raise 154 * AlreadyRealized exception 155 * 156 * @param w the widget to add. The pack does not create a 157 * copy, so the pointer has to remain valid for the lifetime 158 * of the pack. 159 */ 160 void add_front(WidgetBase* w); 161 162 /** 163 * Add a widget to the Pack. The widget will be added after 164 * all other widget. 165 * 166 * @important Widgets can only be added before the Pack is 167 * realized. It is not possible to add a Widget after the pack 168 * has been realized. Attempt to do so will raise 169 * AlreadyRealized exception 170 * 171 * @param w the widget to add. The pack does not create a 172 * copy, so the pointer has to remain valid for the lifetime 173 * of the pack. 174 */ 175 void add_back(WidgetBase* w); 176 177 /** 178 * Remove a previously added widget. 179 * 180 * @important Widgets can only be added before the Pack is 181 * realized. It is not possible to add a Widget after the pack 182 * has been realized. Attempt to do so will raise 183 * AlreadyRealized exception 184 * 185 * @param w widget to be removed. Pack compares the address 186 * of the widget. 187 */ 188 void remove(WidgetBase* w); 189 190 /** 191 * Set the curses window of the Pack and all associated 192 * Widgets. 193 * 194 * Pack has to maintain its curses window pointer as well as 195 * the pointer of the associated widgets. 196 * 197 * @param p pointer to curses window 198 */ 199 void curses_window(YACURS::INTERNAL::CursWin* p); 200 201 /** 202 * Set the Focus Group ID of the Pack and all associated 203 * Widgets. 204 * 205 * @param id Focus Group ID. 206 */ 207 void focusgroup_id(FocusManager::fgid_t id); 208 209 /** 210 * Set the available size. 211 * 212 * Since Pack is dynamically sizeable, we have to react on 213 * size_available(), unlike statically sized Widgets. 214 * 215 * @param s the size available to the Pack. 216 */ 217 void size_available(const Size& s); 218 219 Size size() const; 220 221 /** 222 * Enable/disable hinting mode. 223 * 224 * When hinting is disabled, size_hint() will always return 225 * Size::zero(), else it uses size_hint() of associated 226 * Widgets. 227 * 228 * By default, hinting is enabled. 229 * 230 * @param h @c true enables hinting, @c false disables 231 * hinting. 232 */ 233 void hinting(bool h); 234 235 /** 236 * Query hinting mode. 237 * 238 * @return @c true if hinting is enabled, @c false otherwise. 239 * 240 * @sa hinting() 241 */ 242 bool hinting() const; 243 244 /** 245 * Enable/disable always dynamic mode. 246 * 247 * If always dynamic is disabled, the pack will behave like a 248 * non-dynamic Widget, if, and only if, it does not contain 249 * any dynamicially sized Widgets. Else it behaves like a 250 * dynamic Widget. 251 * 252 * If always dynmic is enabled, it behaves always like a 253 * dynamic widget. 254 * 255 * By default, always dynamic is disabled. 256 * 257 * @param d @c true to enable always dynamic mode, @c false 258 * to disable it. 259 */ 260 void always_dynamic(bool d); 261 262 /** 263 * Query always dynamic mode. 264 * 265 * @return @c true if always dynamic mode is enabled, @c false 266 * otherwise. 267 */ 268 bool always_dynamic() const; 269 270 void reset_size(); 271 272 /** 273 * Handle a size change in an associated Widget. 274 * 275 * If the pack has a parent, the notification is passed 276 * further up. Else it will handle the notification by calling 277 * Pack::resize(). 278 * 279 * @return @c true if the notification can be handled, @c 280 * false otherwise. 281 */ 282 bool size_change(); 283 284 bool can_focus() const; 285 286 void focus(bool); 287 288 bool focus() const; 289 290 /** 291 * Refresh all Widgets in the Pack. 292 * 293 * @param immediate @see Realizeable 294 */ 295 void refresh(bool immediate); 296 297 /** 298 * Resize the pack. 299 * 300 * This function relies on the implementation of realize() of 301 * derived classes. 302 * 303 * @param a the new size available to the pack. 304 */ 305 void resize(const Area& a); 306 307 // 308 // Has to be implemented in derrived classes 309 // void realize(); 310 }; 311 } // namespace YACURS 312 313 #endif // PACK_H 314