Window 21 KB

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