| 1 | /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield |
|---|
| 2 | * |
|---|
| 3 | * This library is open source and may be redistributed and/or modified under |
|---|
| 4 | * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or |
|---|
| 5 | * (at your option) any later version. The full license is in LICENSE file |
|---|
| 6 | * included with this distribution, and on the openscenegraph.org website. |
|---|
| 7 | * |
|---|
| 8 | * This library is distributed in the hope that it will be useful, |
|---|
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 11 | * OpenSceneGraph Public License for more details. |
|---|
| 12 | */ |
|---|
| 13 | |
|---|
| 14 | // Code by: Jeremy Moles (cubicool) 2007-2008 |
|---|
| 15 | |
|---|
| 16 | #ifndef OSGWIDGET_WINDOW |
|---|
| 17 | #define OSGWIDGET_WINDOW |
|---|
| 18 | |
|---|
| 19 | #include <osg/Scissor> |
|---|
| 20 | #include <osg/MatrixTransform> |
|---|
| 21 | #include <osg/Geode> |
|---|
| 22 | #include <osg/ClipNode> |
|---|
| 23 | #include <osgWidget/Types> |
|---|
| 24 | #include <osgWidget/Util> |
|---|
| 25 | #include <osgWidget/Widget> |
|---|
| 26 | |
|---|
| 27 | namespace osgWidget { |
|---|
| 28 | |
|---|
| 29 | // These are helper callbacks you can attach to Windows that will make them moveable, |
|---|
| 30 | // rotatable, and scalable respectively. |
|---|
| 31 | bool OSGWIDGET_EXPORT callbackWindowMove (Event&); |
|---|
| 32 | bool OSGWIDGET_EXPORT callbackWindowRotate (Event&); |
|---|
| 33 | bool OSGWIDGET_EXPORT callbackWindowScale (Event&); |
|---|
| 34 | |
|---|
| 35 | // These are helper callbacks you can attach to Windows to that will make various |
|---|
| 36 | // keyboard events behave as you might imagine. |
|---|
| 37 | bool OSGWIDGET_EXPORT callbackWindowTabFocus(Event&); |
|---|
| 38 | |
|---|
| 39 | class OSGWIDGET_EXPORT Window: |
|---|
| 40 | public osg::MatrixTransform, |
|---|
| 41 | public UIObjectParent<Widget>, |
|---|
| 42 | public EventInterface, |
|---|
| 43 | public StyleInterface |
|---|
| 44 | { |
|---|
| 45 | public: |
|---|
| 46 | typedef std::list<osg::observer_ptr<Window> > WindowList; |
|---|
| 47 | |
|---|
| 48 | struct Sizes |
|---|
| 49 | { |
|---|
| 50 | point_type current; |
|---|
| 51 | point_type minimum; |
|---|
| 52 | |
|---|
| 53 | Sizes(point_type c = -1.0f, point_type m = -1.0f): |
|---|
| 54 | current(c), |
|---|
| 55 | minimum(m) {} |
|---|
| 56 | }; |
|---|
| 57 | |
|---|
| 58 | // TODO: This is a class that puts (embeds) the Window inside of a Widget |
|---|
| 59 | // interface, to help assemble Windows with Windows, and what have you. |
|---|
| 60 | class OSGWIDGET_EXPORT EmbeddedWindow: public Widget { |
|---|
| 61 | osg::ref_ptr<Window> _window; |
|---|
| 62 | |
|---|
| 63 | public: |
|---|
| 64 | META_Object (osgWidget::Window, EmbeddedWindow); |
|---|
| 65 | |
|---|
| 66 | EmbeddedWindow (const std::string& = "", point_type = 0.0f, point_type = 0.0f); |
|---|
| 67 | EmbeddedWindow (const EmbeddedWindow&, const osg::CopyOp&); |
|---|
| 68 | |
|---|
| 69 | virtual void parented (Window*); |
|---|
| 70 | virtual void unparented (Window*); |
|---|
| 71 | virtual void managed (WindowManager*); |
|---|
| 72 | virtual void unmanaged (WindowManager*); |
|---|
| 73 | virtual void positioned (); |
|---|
| 74 | |
|---|
| 75 | bool setWindow (Window*); |
|---|
| 76 | void updateSizeFromWindow (); |
|---|
| 77 | |
|---|
| 78 | Window* getWindow() { |
|---|
| 79 | return _window.get(); |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | const Window* getWindow() const { |
|---|
| 83 | return _window.get(); |
|---|
| 84 | } |
|---|
| 85 | }; |
|---|
| 86 | |
|---|
| 87 | // These correspond to special regions honored by the WindowManager. Most Windows |
|---|
| 88 | // will want to be NONE, unless they need to exist in the foreground or background |
|---|
| 89 | // for some reason. |
|---|
| 90 | enum Strata { |
|---|
| 91 | STRATA_NONE, |
|---|
| 92 | STRATA_BACKGROUND, |
|---|
| 93 | STRATA_FOREGROUND |
|---|
| 94 | }; |
|---|
| 95 | |
|---|
| 96 | // If you only want to display a portion of a Window (such as when it is embedded), |
|---|
| 97 | // you will need to set the VisibilityMode to WM_PARTIAL. Otherwise, the entire |
|---|
| 98 | // Window is visible by default. The final enum, VM_ENTIRE, says that no Scissoring |
|---|
| 99 | // should take place at all, and is useful in cases where you want to properly |
|---|
| 100 | // scale or rotate Windows. |
|---|
| 101 | enum VisibilityMode { |
|---|
| 102 | VM_FULL, |
|---|
| 103 | VM_PARTIAL, |
|---|
| 104 | VM_ENTIRE |
|---|
| 105 | }; |
|---|
| 106 | |
|---|
| 107 | // Anchors are very similar in that they allow us to pre-apply transformations in the |
|---|
| 108 | // call to Window::update() that allow us to position a Window somewhere relative |
|---|
| 109 | // to the WindowManger's viewable area. However, unlike the ALIGNMENT enums, these |
|---|
| 110 | // are totally optional (whereas a Widget must always have some ALIGNMENT value set. |
|---|
| 111 | enum VerticalAnchor { |
|---|
| 112 | VA_NONE, |
|---|
| 113 | VA_CENTER, |
|---|
| 114 | VA_TOP, |
|---|
| 115 | VA_BOTTOM |
|---|
| 116 | }; |
|---|
| 117 | |
|---|
| 118 | enum HorizontalAnchor { |
|---|
| 119 | HA_NONE, |
|---|
| 120 | HA_CENTER, |
|---|
| 121 | HA_LEFT, |
|---|
| 122 | HA_RIGHT |
|---|
| 123 | }; |
|---|
| 124 | |
|---|
| 125 | Window (const std::string& = ""); |
|---|
| 126 | Window (const Window&, const osg::CopyOp&); |
|---|
| 127 | |
|---|
| 128 | bool resize (point_type = 0.0f, point_type = 0.0f); |
|---|
| 129 | bool resizeAdd (point_type = 0.0f, point_type = 0.0f); |
|---|
| 130 | bool resizePercent (point_type = 0.0f, point_type = 0.0f); |
|---|
| 131 | |
|---|
| 132 | virtual void update (); |
|---|
| 133 | virtual void managed (WindowManager*); |
|---|
| 134 | virtual void unmanaged (WindowManager*); |
|---|
| 135 | virtual bool addWidget (Widget*); |
|---|
| 136 | virtual bool insertWidget (Widget*, unsigned int); |
|---|
| 137 | virtual bool removeWidget (Widget*); |
|---|
| 138 | virtual bool replaceWidget (Widget*, Widget*); |
|---|
| 139 | |
|---|
| 140 | // This method wraps our Geode's addDrawable() method and returns the index of |
|---|
| 141 | // the newly-added Drawable. |
|---|
| 142 | unsigned int addDrawableAndGetIndex (osg::Drawable*); |
|---|
| 143 | unsigned int addChildAndGetIndex (osg::Node*); |
|---|
| 144 | |
|---|
| 145 | bool isVisible () const; |
|---|
| 146 | bool isXYWithinVisible (float, float) const; |
|---|
| 147 | void setVisibleArea (int = 0, int = 0, int = 0, int = 0); |
|---|
| 148 | void addVisibleArea (int = 0, int = 0, int = 0, int = 0); |
|---|
| 149 | bool setFocused (const Widget*); |
|---|
| 150 | bool setFocused (const std::string&); |
|---|
| 151 | bool grabFocus (); |
|---|
| 152 | bool setFirstFocusable (); |
|---|
| 153 | bool setNextFocusable (); |
|---|
| 154 | bool getFocusList (WidgetList&) const; |
|---|
| 155 | bool getEmbeddedList (WindowList&) const; |
|---|
| 156 | void getParentList (WindowList&) const; |
|---|
| 157 | |
|---|
| 158 | XYCoord localXY (double, double) const; |
|---|
| 159 | XYCoord getAbsoluteOrigin () const; |
|---|
| 160 | |
|---|
| 161 | // This method wraps the current Window in a EmbeddedWindow object and returns it. |
|---|
| 162 | EmbeddedWindow* embed( |
|---|
| 163 | const std::string& = "", |
|---|
| 164 | Widget::Layer = Widget::LAYER_MIDDLE, |
|---|
| 165 | unsigned int = 0 |
|---|
| 166 | ); |
|---|
| 167 | |
|---|
| 168 | Widget* getFocused() { |
|---|
| 169 | return _focused.get(); |
|---|
| 170 | } |
|---|
| 171 | |
|---|
| 172 | const Widget* getFocused() const { |
|---|
| 173 | return _focused.get(); |
|---|
| 174 | } |
|---|
| 175 | |
|---|
| 176 | bool show() { |
|---|
| 177 | return _setVisible(true); |
|---|
| 178 | } |
|---|
| 179 | |
|---|
| 180 | bool hide() { |
|---|
| 181 | return _setVisible(false); |
|---|
| 182 | } |
|---|
| 183 | |
|---|
| 184 | bool isPointerXYWithinVisible(float x, float y) const { |
|---|
| 185 | XYCoord xy = localXY(x, y); |
|---|
| 186 | |
|---|
| 187 | return isXYWithinVisible(xy.x(), xy.y()); |
|---|
| 188 | } |
|---|
| 189 | |
|---|
| 190 | osg::Geode* getGeode() { |
|---|
| 191 | return _geode(); |
|---|
| 192 | } |
|---|
| 193 | |
|---|
| 194 | const osg::Geode* getGeode() const { |
|---|
| 195 | return _geode(); |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | Widget* getBackground() { |
|---|
| 199 | return _bg(); |
|---|
| 200 | } |
|---|
| 201 | |
|---|
| 202 | const Widget* getBackground() const { |
|---|
| 203 | return _bg(); |
|---|
| 204 | } |
|---|
| 205 | |
|---|
| 206 | WindowManager* getWindowManager() { |
|---|
| 207 | return _wm; |
|---|
| 208 | } |
|---|
| 209 | |
|---|
| 210 | const WindowManager* getWindowManager() const { |
|---|
| 211 | return _wm; |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | Window* getParent() { |
|---|
| 215 | return _parent; |
|---|
| 216 | } |
|---|
| 217 | |
|---|
| 218 | const Window* getParent() const { |
|---|
| 219 | return _parent; |
|---|
| 220 | } |
|---|
| 221 | |
|---|
| 222 | Window* getTopmostParent() { |
|---|
| 223 | return _getTopmostParent(); |
|---|
| 224 | } |
|---|
| 225 | |
|---|
| 226 | const Window* getTopmostParent() const { |
|---|
| 227 | return _getTopmostParent(); |
|---|
| 228 | } |
|---|
| 229 | |
|---|
| 230 | unsigned int getIndex() const { |
|---|
| 231 | return _index; |
|---|
| 232 | } |
|---|
| 233 | |
|---|
| 234 | matrix_type getX() const { |
|---|
| 235 | return _x; |
|---|
| 236 | } |
|---|
| 237 | |
|---|
| 238 | matrix_type getY() const { |
|---|
| 239 | return _y; |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | matrix_type getZ() const { |
|---|
| 243 | return _z; |
|---|
| 244 | } |
|---|
| 245 | |
|---|
| 246 | point_type getWidth() const { |
|---|
| 247 | return _width.current; |
|---|
| 248 | } |
|---|
| 249 | |
|---|
| 250 | point_type getHeight() const { |
|---|
| 251 | return _height.current; |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | point_type getMinWidth() const { |
|---|
| 255 | return _width.minimum; |
|---|
| 256 | } |
|---|
| 257 | |
|---|
| 258 | point_type getMinHeight() const { |
|---|
| 259 | return _height.minimum; |
|---|
| 260 | } |
|---|
| 261 | |
|---|
| 262 | VerticalAnchor getAnchorVertical() const { |
|---|
| 263 | return _vAnchor; |
|---|
| 264 | } |
|---|
| 265 | |
|---|
| 266 | HorizontalAnchor getAnchorHorizontal() const { |
|---|
| 267 | return _hAnchor; |
|---|
| 268 | } |
|---|
| 269 | |
|---|
| 270 | XYCoord getOrigin() const { |
|---|
| 271 | return XYCoord(_x, _y); |
|---|
| 272 | } |
|---|
| 273 | |
|---|
| 274 | XYCoord getSize() const { |
|---|
| 275 | return XYCoord(_width.current, _height.current); |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | XYCoord getMinSize() const { |
|---|
| 279 | return XYCoord(_width.minimum, _height.minimum); |
|---|
| 280 | } |
|---|
| 281 | |
|---|
| 282 | matrix_type getZRange() const { |
|---|
| 283 | return _zRange; |
|---|
| 284 | } |
|---|
| 285 | |
|---|
| 286 | Strata getStrata() const { |
|---|
| 287 | return _strata; |
|---|
| 288 | } |
|---|
| 289 | |
|---|
| 290 | const Quad& getVisibleArea() const { |
|---|
| 291 | return _visibleArea; |
|---|
| 292 | } |
|---|
| 293 | |
|---|
| 294 | VisibilityMode getVisibilityMode() const { |
|---|
| 295 | return _vis; |
|---|
| 296 | } |
|---|
| 297 | |
|---|
| 298 | Point getPosition() const { |
|---|
| 299 | return Point(_x, _y, _z); |
|---|
| 300 | } |
|---|
| 301 | |
|---|
| 302 | matrix_type getRotate() const { |
|---|
| 303 | return _r; |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | matrix_type getScale() const { |
|---|
| 307 | return _s; |
|---|
| 308 | } |
|---|
| 309 | |
|---|
| 310 | matrix_type getScaleDenominator() const { |
|---|
| 311 | return _scaleDenom; |
|---|
| 312 | } |
|---|
| 313 | |
|---|
| 314 | void setX(matrix_type x) { |
|---|
| 315 | _x = x; |
|---|
| 316 | } |
|---|
| 317 | |
|---|
| 318 | void setY(matrix_type y) { |
|---|
| 319 | _y = y; |
|---|
| 320 | } |
|---|
| 321 | |
|---|
| 322 | void setZ(matrix_type z) { |
|---|
| 323 | _z = z; |
|---|
| 324 | } |
|---|
| 325 | |
|---|
| 326 | void setZRange(matrix_type zRange) { |
|---|
| 327 | _zRange = zRange; |
|---|
| 328 | } |
|---|
| 329 | |
|---|
| 330 | void setPosition(matrix_type x, matrix_type y, matrix_type z) { |
|---|
| 331 | _x = x; |
|---|
| 332 | _y = y; |
|---|
| 333 | _z = z; |
|---|
| 334 | } |
|---|
| 335 | |
|---|
| 336 | void setPosition(const Point& p) { |
|---|
| 337 | setPosition(p.x(), p.y(), p.z()); |
|---|
| 338 | } |
|---|
| 339 | |
|---|
| 340 | void setOrigin(matrix_type x, matrix_type y) { |
|---|
| 341 | _x = x; |
|---|
| 342 | _y = y; |
|---|
| 343 | } |
|---|
| 344 | |
|---|
| 345 | void setOrigin(const XYCoord& xy) { |
|---|
| 346 | setOrigin(xy.x(), xy.y()); |
|---|
| 347 | } |
|---|
| 348 | |
|---|
| 349 | void setRotate(matrix_type r) { |
|---|
| 350 | _r = r; |
|---|
| 351 | } |
|---|
| 352 | |
|---|
| 353 | void setScale(matrix_type s) { |
|---|
| 354 | _s = s; |
|---|
| 355 | } |
|---|
| 356 | |
|---|
| 357 | void setScaleDenominator(matrix_type sd) { |
|---|
| 358 | _scaleDenom = sd; |
|---|
| 359 | } |
|---|
| 360 | |
|---|
| 361 | void setAnchorVertical(VerticalAnchor va) { |
|---|
| 362 | _vAnchor = va; |
|---|
| 363 | } |
|---|
| 364 | |
|---|
| 365 | void setAnchorHorizontal(HorizontalAnchor ha) { |
|---|
| 366 | _hAnchor = ha; |
|---|
| 367 | } |
|---|
| 368 | |
|---|
| 369 | void setStrata(Strata s) { |
|---|
| 370 | _strata = s; |
|---|
| 371 | } |
|---|
| 372 | |
|---|
| 373 | void setVisibilityMode(VisibilityMode v) { |
|---|
| 374 | _vis = v; |
|---|
| 375 | } |
|---|
| 376 | |
|---|
| 377 | void addX(matrix_type x) { |
|---|
| 378 | _x += x; |
|---|
| 379 | } |
|---|
| 380 | |
|---|
| 381 | void addY(matrix_type y) { |
|---|
| 382 | _y += y; |
|---|
| 383 | } |
|---|
| 384 | |
|---|
| 385 | void addZ(matrix_type z) { |
|---|
| 386 | _z += z; |
|---|
| 387 | } |
|---|
| 388 | |
|---|
| 389 | void addRotate(matrix_type r) { |
|---|
| 390 | _r += r; |
|---|
| 391 | } |
|---|
| 392 | |
|---|
| 393 | void addScale(matrix_type s) { |
|---|
| 394 | _s += s / (_scaleDenom != 0.0f ? _scaleDenom : 1.0f); |
|---|
| 395 | } |
|---|
| 396 | |
|---|
| 397 | void addOrigin(matrix_type x, matrix_type y) { |
|---|
| 398 | _x += x; |
|---|
| 399 | _y += y; |
|---|
| 400 | } |
|---|
| 401 | |
|---|
| 402 | void attachMoveCallback() { |
|---|
| 403 | addCallback(new Callback(&callbackWindowMove, EVENT_MOUSE_DRAG)); |
|---|
| 404 | } |
|---|
| 405 | |
|---|
| 406 | void attachRotateCallback() { |
|---|
| 407 | addCallback(new Callback(&callbackWindowRotate, EVENT_MOUSE_DRAG)); |
|---|
| 408 | } |
|---|
| 409 | |
|---|
| 410 | void attachScaleCallback() { |
|---|
| 411 | addCallback(new Callback(&callbackWindowScale, EVENT_MOUSE_DRAG)); |
|---|
| 412 | } |
|---|
| 413 | |
|---|
| 414 | void attachTabFocusCallback() { |
|---|
| 415 | addCallback(new Callback(&callbackWindowTabFocus, EVENT_KEY_DOWN)); |
|---|
| 416 | } |
|---|
| 417 | |
|---|
| 418 | typedef point_type (Widget::*Getter)() const; |
|---|
| 419 | |
|---|
| 420 | protected: |
|---|
| 421 | |
|---|
| 422 | typedef std::less<point_type> Less; |
|---|
| 423 | typedef std::greater<point_type> Greater; |
|---|
| 424 | typedef std::plus<point_type> Plus; |
|---|
| 425 | |
|---|
| 426 | friend class WindowManager; |
|---|
| 427 | |
|---|
| 428 | // The (optional) Window that this Window is parented inside. |
|---|
| 429 | Window* _parent; |
|---|
| 430 | |
|---|
| 431 | // The WindowManger to which this window is attached. |
|---|
| 432 | WindowManager* _wm; |
|---|
| 433 | |
|---|
| 434 | // The positional index this Node holds within it's parent WindowManager. |
|---|
| 435 | unsigned int _index; |
|---|
| 436 | |
|---|
| 437 | // The X and Y values of the Window (origin). |
|---|
| 438 | matrix_type _x; |
|---|
| 439 | matrix_type _y; |
|---|
| 440 | |
|---|
| 441 | // A pair of values representing the currently calculated Z value and the |
|---|
| 442 | // depth range for all children to be used during the call to update(). |
|---|
| 443 | matrix_type _z; |
|---|
| 444 | matrix_type _zRange; |
|---|
| 445 | |
|---|
| 446 | // This is a special value that can be used to "force" a Window not to be |
|---|
| 447 | // focusable and instead always exist in the foreground or background. |
|---|
| 448 | Strata _strata; |
|---|
| 449 | |
|---|
| 450 | // A flag determining whether our visible area is the full Window or rather |
|---|
| 451 | // a portion of the Window. |
|---|
| 452 | VisibilityMode _vis; |
|---|
| 453 | |
|---|
| 454 | // A rotation value in degrees. |
|---|
| 455 | matrix_type _r; |
|---|
| 456 | |
|---|
| 457 | // This will also need to adjust geom internally so that picking is correct. |
|---|
| 458 | matrix_type _s; |
|---|
| 459 | |
|---|
| 460 | matrix_type _scaleDenom; |
|---|
| 461 | |
|---|
| 462 | Sizes _width; |
|---|
| 463 | Sizes _height; |
|---|
| 464 | |
|---|
| 465 | VerticalAnchor _vAnchor; |
|---|
| 466 | HorizontalAnchor _hAnchor; |
|---|
| 467 | |
|---|
| 468 | // Not all windows have widgets that can focus, but if they do this should |
|---|
| 469 | // be a pointer to it. |
|---|
| 470 | osg::observer_ptr<Widget> _focused; |
|---|
| 471 | |
|---|
| 472 | // The "visible" area that will define both the glScissor bounds AND will |
|---|
| 473 | // be used to make sure our pick is valid. The values herein correspond to |
|---|
| 474 | // X, Y, W, and H--in that order. |
|---|
| 475 | Quad _visibleArea; |
|---|
| 476 | |
|---|
| 477 | // This helper method is used by _compare<>() and _accumulate<>(), so ignore this |
|---|
| 478 | // function and go see the docs for those instead. This thing is huge and unwieldy |
|---|
| 479 | // and not to be triffled with! :) |
|---|
| 480 | template<typename T> |
|---|
| 481 | point_type _forEachAssignOrApply( |
|---|
| 482 | Getter get, |
|---|
| 483 | int begin, |
|---|
| 484 | int end, |
|---|
| 485 | int add, |
|---|
| 486 | bool assign |
|---|
| 487 | ) const { |
|---|
| 488 | point_type val = 0.0f; |
|---|
| 489 | unsigned int c = begin; |
|---|
| 490 | |
|---|
| 491 | ConstIterator e = end > 0 ? _objects.begin() + end : _objects.end() + end; |
|---|
| 492 | |
|---|
| 493 | // I WARNED YOU! If you try and understand what this does your head will |
|---|
| 494 | // explode! But let me say a few things: in MSVC you can't add to an iterator |
|---|
| 495 | // such that the add will cause it to increment past the end of the container. |
|---|
| 496 | // This appears to be safe in GCC, where it will just return the last |
|---|
| 497 | // item therein, but causes an assertion error in other compilers. I'm not |
|---|
| 498 | // sure if there is a cleaner remedy for this, so what we do for now is keep a |
|---|
| 499 | // count variable called "c" that makes sure our iterator's opterator+() |
|---|
| 500 | // method is safe to call. |
|---|
| 501 | for( |
|---|
| 502 | ConstIterator i = _objects.begin() + begin; |
|---|
| 503 | i < e; |
|---|
| 504 | c += add |
|---|
| 505 | ) { |
|---|
| 506 | point_type v = 0.0f; |
|---|
| 507 | |
|---|
| 508 | if(i->valid()) v = (i->get()->*get)(); |
|---|
| 509 | |
|---|
| 510 | // If you want to assign to val, and NOT add a sequence of them... |
|---|
| 511 | if(assign) { |
|---|
| 512 | if(T()(v, val)) val = v; |
|---|
| 513 | } |
|---|
| 514 | |
|---|
| 515 | // If you want to accumulate a value INTO val... |
|---|
| 516 | else val = T()(v, val); |
|---|
| 517 | |
|---|
| 518 | // Make sure our iterator is safe to increment. Otherwise, set it to |
|---|
| 519 | // whatever end is. |
|---|
| 520 | // TODO: This isn't 100% accurate, as it does not YET take into account |
|---|
| 521 | // our requested end in any way other than implicitly. It should, however, |
|---|
| 522 | // work okay for now. |
|---|
| 523 | if((c + add) < _objects.size()) i += add; |
|---|
| 524 | |
|---|
| 525 | else i = e; |
|---|
| 526 | } |
|---|
| 527 | |
|---|
| 528 | return val; |
|---|
| 529 | } |
|---|
| 530 | |
|---|
| 531 | void _setWidthAndHeightUnknownSizeError (const std::string&, point_type); |
|---|
| 532 | void _setWidthAndHeightNotPAError (const std::string&, point_type); |
|---|
| 533 | void _setWidthAndHeight (); |
|---|
| 534 | void _removeFromGeode (Widget*); |
|---|
| 535 | |
|---|
| 536 | Widget* _getBackground() const; |
|---|
| 537 | Window* _getTopmostParent() const; |
|---|
| 538 | |
|---|
| 539 | // This method will return the T'th value returned by applying the Getter member function |
|---|
| 540 | // pointer to each iterator in the range of iterators defined by offset and add. In |
|---|
| 541 | // plain language, this helper method will apply some standard Widget::get* function |
|---|
| 542 | // to a range of objects in the _objects Vector, and will return the T'th of that. |
|---|
| 543 | // The template T can be any functor accepting two point_type values that return |
|---|
| 544 | // a bool. For example, this is commonly used with std::less to find the smallest |
|---|
| 545 | // width in a range of Widgets. |
|---|
| 546 | template<typename T> |
|---|
| 547 | point_type _compare( |
|---|
| 548 | Getter get, |
|---|
| 549 | int begin = 0, |
|---|
| 550 | int end = 0, |
|---|
| 551 | int add = 1 |
|---|
| 552 | ) const { |
|---|
| 553 | return _forEachAssignOrApply<T>(get, begin, end, add, true); |
|---|
| 554 | } |
|---|
| 555 | |
|---|
| 556 | // This method will return the T'th value accumulated by applying the Getter member |
|---|
| 557 | // function to each iterator in the range of iterators defined by offset and add (similar |
|---|
| 558 | // to above). For example, this method can be used to apply std::plus to every |
|---|
| 559 | // width in a range of Widgets, and return the total. |
|---|
| 560 | template<typename T> |
|---|
| 561 | point_type _accumulate( |
|---|
| 562 | Getter get, |
|---|
| 563 | int begin = 0, |
|---|
| 564 | int end = 0, |
|---|
| 565 | int add = 1 |
|---|
| 566 | ) const { |
|---|
| 567 | return _forEachAssignOrApply<T>(get, begin, end, add, false); |
|---|
| 568 | } |
|---|
| 569 | |
|---|
| 570 | osg::Geode* _geode() { |
|---|
| 571 | return dynamic_cast<osg::Geode*>(getChild(0)); |
|---|
| 572 | } |
|---|
| 573 | |
|---|
| 574 | const osg::Geode* _geode() const { |
|---|
| 575 | return dynamic_cast<const osg::Geode*>(getChild(0)); |
|---|
| 576 | } |
|---|
| 577 | |
|---|
| 578 | Widget* _bg() { |
|---|
| 579 | return _getBackground(); |
|---|
| 580 | } |
|---|
| 581 | |
|---|
| 582 | const Widget* _bg() const { |
|---|
| 583 | return _getBackground(); |
|---|
| 584 | } |
|---|
| 585 | |
|---|
| 586 | osg::Scissor* _scissor() { |
|---|
| 587 | return dynamic_cast<osg::Scissor*>( |
|---|
| 588 | getStateSet()->getAttribute(osg::StateAttribute::SCISSOR) |
|---|
| 589 | ); |
|---|
| 590 | } |
|---|
| 591 | |
|---|
| 592 | bool _setWidget (Widget*, int = -1); |
|---|
| 593 | bool _setVisible (bool); |
|---|
| 594 | void _setFocused (Widget*); |
|---|
| 595 | void _setStyled (Widget*); |
|---|
| 596 | void _setParented (Widget*, bool=false); |
|---|
| 597 | void _setManaged (Widget*, bool=false); |
|---|
| 598 | |
|---|
| 599 | void _positionWidget(Widget*, point_type, point_type); |
|---|
| 600 | |
|---|
| 601 | // These return the smallest and largest width and height values for the given |
|---|
| 602 | // range of Widgets. |
|---|
| 603 | point_type _getMinWidgetWidth (int = 0, int = 0, int = 1) const; |
|---|
| 604 | point_type _getMinWidgetHeight (int = 0, int = 0, int = 1) const; |
|---|
| 605 | point_type _getMaxWidgetWidth (int = 0, int = 0, int = 1) const; |
|---|
| 606 | point_type _getMaxWidgetHeight (int = 0, int = 0, int = 1) const; |
|---|
| 607 | |
|---|
| 608 | // These return the smallest and largest minWidth and minHeight values for |
|---|
| 609 | // the given range of Widgets. |
|---|
| 610 | point_type _getMinWidgetMinWidth (int = 0, int = 0, int = 1) const; |
|---|
| 611 | point_type _getMinWidgetMinHeight (int = 0, int = 0, int = 1) const; |
|---|
| 612 | point_type _getMaxWidgetMinWidth (int = 0, int = 0, int = 1) const; |
|---|
| 613 | point_type _getMaxWidgetMinHeight (int = 0, int = 0, int = 1) const; |
|---|
| 614 | |
|---|
| 615 | // These return the smallest and largest width and height total (width + pad) |
|---|
| 616 | // values for the given range of Widgets. |
|---|
| 617 | point_type _getMinWidgetWidthTotal (int = 0, int = 0, int = 1) const; |
|---|
| 618 | point_type _getMinWidgetHeightTotal (int = 0, int = 0, int = 1) const; |
|---|
| 619 | point_type _getMaxWidgetWidthTotal (int = 0, int = 0, int = 1) const; |
|---|
| 620 | point_type _getMaxWidgetHeightTotal (int = 0, int = 0, int = 1) const; |
|---|
| 621 | |
|---|
| 622 | // These return the smallest and largest minWidth and minHeight total |
|---|
| 623 | // (width + pad) values for the given range of Widgets. |
|---|
| 624 | point_type _getMinWidgetMinWidthTotal (int = 0, int = 0, int = 1) const; |
|---|
| 625 | point_type _getMinWidgetMinHeightTotal (int = 0, int = 0, int = 1) const; |
|---|
| 626 | point_type _getMaxWidgetMinWidthTotal (int = 0, int = 0, int = 1) const; |
|---|
| 627 | point_type _getMaxWidgetMinHeightTotal (int = 0, int = 0, int = 1) const; |
|---|
| 628 | |
|---|
| 629 | // These return the smallest and largest horizontal and vertical padding |
|---|
| 630 | // values for the given range of Widgets. |
|---|
| 631 | point_type _getMinWidgetPadHorizontal (int = 0, int = 0, int = 1) const; |
|---|
| 632 | point_type _getMinWidgetPadVertical (int = 0, int = 0, int = 1) const; |
|---|
| 633 | point_type _getMaxWidgetPadHorizontal (int = 0, int = 0, int = 1) const; |
|---|
| 634 | point_type _getMaxWidgetPadVertical (int = 0, int = 0, int = 1) const; |
|---|
| 635 | |
|---|
| 636 | point_type _getNumFill(int = 0, int = 0, int = 1) const; |
|---|
| 637 | |
|---|
| 638 | // This method is passed the additional values by which width and height should be |
|---|
| 639 | // modified as calculed by the parent method, Window::resize. Keep in mind that these |
|---|
| 640 | // values can be negative (indicating a potential "shrink" request) or positive (which |
|---|
| 641 | // would indicate a "grow" reqeust). |
|---|
| 642 | virtual void _resizeImplementation(point_type, point_type) = 0; |
|---|
| 643 | |
|---|
| 644 | // These are made into implementation functions since getting the width or height |
|---|
| 645 | // of a window can potentially be an expensive operation, and we'll want to cache |
|---|
| 646 | // results if possible (which is handled transparently by the actualy Window::resize |
|---|
| 647 | // method). They return a Sizes struct which contains two members: cur (for current) |
|---|
| 648 | // and min (minimum). It's important that the Window know it's minimum possible |
|---|
| 649 | // size so that it can ignore invaled requests to resize. |
|---|
| 650 | // |
|---|
| 651 | // Default versions using BoundingBox calculations are provided, but some Windows |
|---|
| 652 | // override this (Table, Box). |
|---|
| 653 | virtual Sizes _getWidthImplementation () const; |
|---|
| 654 | virtual Sizes _getHeightImplementation () const; |
|---|
| 655 | |
|---|
| 656 | }; |
|---|
| 657 | |
|---|
| 658 | typedef Window::WindowList WindowList; |
|---|
| 659 | |
|---|
| 660 | } |
|---|
| 661 | |
|---|
| 662 | #endif |
|---|