Widget 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  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_WIDGET
  15. #define OSGWIDGET_WIDGET
  16. #include <osg/Texture2D>
  17. #include <osgWidget/EventInterface>
  18. #include <osgWidget/StyleInterface>
  19. #include <osgWidget/UIObjectParent>
  20. #include <osgWidget/Types>
  21. namespace osgWidget {
  22. class Window;
  23. class WindowManager;
  24. // A Widget is a rectangular region that receives events about the state of various input
  25. // devices such as the pointer and keyboard. It is aware of it's width, height, and origin but
  26. // nothing else. It is the job of higher-level container objects to organize layouts and
  27. // the like, and to contextualize the meaning of the widgets "origin" (whether it is absolute
  28. // or relative).
  29. class OSGWIDGET_EXPORT Widget: public osg::Geometry, public EventInterface, public StyleInterface {
  30. public:
  31. enum Corner {
  32. LOWER_LEFT = 0,
  33. LOWER_RIGHT = 1,
  34. UPPER_RIGHT = 2,
  35. UPPER_LEFT = 3,
  36. LL = LOWER_LEFT,
  37. LR = LOWER_RIGHT,
  38. UR = UPPER_RIGHT,
  39. UL = UPPER_LEFT,
  40. ALL_CORNERS = 4
  41. };
  42. enum Layer {
  43. LAYER_TOP = 100,
  44. LAYER_HIGH = 75,
  45. LAYER_MIDDLE = 50,
  46. LAYER_LOW = 25,
  47. LAYER_BG = 0
  48. };
  49. enum VerticalAlignment {
  50. VA_CENTER,
  51. VA_TOP,
  52. VA_BOTTOM
  53. };
  54. enum HorizontalAlignment {
  55. HA_CENTER,
  56. HA_LEFT,
  57. HA_RIGHT
  58. };
  59. enum CoordinateMode {
  60. CM_ABSOLUTE,
  61. CM_RELATIVE
  62. };
  63. Widget (const std::string& = "", point_type = 0.0f, point_type = 0.0f);
  64. Widget (const Widget&, const osg::CopyOp&);
  65. META_Object (osgWidget, Widget);
  66. virtual ~Widget() {
  67. }
  68. // This method is called when the widget is added to a Window; this is useful
  69. // when the widget needs to do something advanced (like a Label). The parent
  70. // is passed as the first argument, although _parent should already be set.
  71. virtual void parented(Window*) {
  72. }
  73. virtual void unparented(Window*) {
  74. }
  75. // This method is called when the widget's parent Window is added to a
  76. // WindowManager object. The base managed method (WHICH YOU MUST REMEMBER
  77. // TO CALL IN YOUR DERIVED METHODS!) sets the TexMat properly depending
  78. // on what coordinate system you're using.
  79. virtual void managed(WindowManager*) {
  80. }
  81. virtual void unmanaged(WindowManager*) {
  82. }
  83. // This method is called when the widget is resized or reallocated in any
  84. // way. This is useful when the widget manages some internal Drawables that need
  85. // to be modified in some way.
  86. virtual void positioned() {
  87. }
  88. void setDimensions(
  89. point_type = -1.0f,
  90. point_type = -1.0f,
  91. point_type = -1.0f,
  92. point_type = -1.0f,
  93. point_type = -1.0f
  94. );
  95. void setPadding (point_type);
  96. void setColor (color_type, color_type, color_type, color_type, Corner = ALL_CORNERS);
  97. void addColor (color_type, color_type, color_type, color_type, Corner = ALL_CORNERS);
  98. void setTexCoord (texcoord_type, texcoord_type, Corner = ALL_CORNERS);
  99. void setLayer (Layer l, unsigned int offset = 0);
  100. // These are additional texture coordinate setting methods.
  101. // This method will use a given origin as the LOWER_LEFT point and texture the
  102. // remaining area based on some width and height values.
  103. void setTexCoordRegion(point_type, point_type, point_type, point_type);
  104. // These are convenience methods for setting up wrapping modes.
  105. void setTexCoordWrapHorizontal ();
  106. void setTexCoordWrapVertical ();
  107. bool setImage (osg::Image*, bool = false, bool = false);
  108. template<class T> bool setImage(const osg::ref_ptr<T>& image, bool f1 = false, bool f2 = false) { return setImage(image.get(), f1, f2); }
  109. bool setImage (const std::string&, bool = false, bool = false);
  110. bool setTexture (osg::Texture*, bool = false, bool = false);
  111. void addX (point_type);
  112. void addY (point_type);
  113. void addWidth (point_type);
  114. void addHeight (point_type);
  115. void addOrigin (point_type, point_type);
  116. void addSize (point_type, point_type);
  117. point_type getWidth () const;
  118. point_type getHeight () const;
  119. point_type getX () const;
  120. point_type getY () const;
  121. point_type getZ () const;
  122. point_type getPadHorizontal () const;
  123. point_type getPadVertical () const;
  124. const Point& getPoint (Corner = ALL_CORNERS) const;
  125. const Color& getColor (Corner = ALL_CORNERS) const;
  126. const TexCoord& getTexCoord (Corner = ALL_CORNERS) const;
  127. Color getImageColorAtXY (point_type x, point_type y) const;
  128. XYCoord localXY (double, double) const;
  129. bool isPaddingUniform() const;
  130. bool isManaged() const {
  131. return _isManaged;
  132. }
  133. bool isStyled() const {
  134. return _isStyled;
  135. }
  136. void setDimensions(const Quad& q, point_type z = -1.0f) {
  137. setDimensions(q[0], q[1], q[2], q[3], z);
  138. }
  139. void setX(point_type x) {
  140. setDimensions(x);
  141. }
  142. void setY(point_type y) {
  143. setDimensions(-1.0f, y);
  144. }
  145. // This method should be use with extreme caution.
  146. void setZ(point_type z) {
  147. setDimensions(-1.0f, -1.0f, -1.0f, -1.0f, z);
  148. }
  149. void setWidth(point_type w) {
  150. setDimensions(-1.0f, -1.0f, w);
  151. }
  152. void setHeight(point_type h) {
  153. setDimensions(-1.0f, -1.0f, -1.0f, h);
  154. }
  155. void setOrigin(point_type x, point_type y) {
  156. setDimensions(x, y);
  157. }
  158. void setOrigin(const XYCoord& xy) {
  159. setOrigin(xy.x(), xy.y());
  160. }
  161. void setSize(point_type w, point_type h) {
  162. setDimensions(-1.0f, -1.0f, w, h);
  163. }
  164. void setSize(const XYCoord& xy) {
  165. setSize(xy.x(), xy.y());
  166. }
  167. void setColor(const Color& col, Corner p = ALL_CORNERS) {
  168. setColor(col.r(), col.g(), col.b(), col.a(), p);
  169. }
  170. void setTexCoord(const XYCoord& xy, Corner p = ALL_CORNERS) {
  171. setTexCoord(xy.x(), xy.y(), p);
  172. }
  173. void setTexCoordRegion(const XYCoord& xy, point_type w, point_type h) {
  174. setTexCoordRegion(xy.x(), xy.y(), w, h);
  175. }
  176. void setTexCoordRegion(point_type x, point_type y, const XYCoord& wh) {
  177. setTexCoordRegion(x, y, wh.x(), wh.y());
  178. }
  179. void setTexCoordRegion(const XYCoord& xy, const XYCoord& wh) {
  180. setTexCoordRegion(xy.x(), xy.y(), wh.x(), wh.y());
  181. }
  182. void addColor(const Color& col, Corner p = ALL_CORNERS) {
  183. addColor(col.r(), col.g(), col.b(), col.a(), p);
  184. }
  185. void addOrigin(const XYCoord& xy) {
  186. addOrigin(xy.x(), xy.y());
  187. }
  188. void addSize(const XYCoord& xy) {
  189. addSize(xy.x(), xy.y());
  190. }
  191. void setMinimumSize(point_type width, point_type height) {
  192. _minWidth = width;
  193. _minHeight = height;
  194. }
  195. void setMinimumSize(const XYCoord& xy) {
  196. setMinimumSize(xy.x(), xy.y());
  197. }
  198. void setPadLeft(point_type p) {
  199. _padLeft = p;
  200. }
  201. void setPadRight(point_type p) {
  202. _padRight = p;
  203. }
  204. void setPadTop(point_type p) {
  205. _padTop = p;
  206. }
  207. void setPadBottom(point_type p) {
  208. _padBottom = p;
  209. }
  210. void setAlignHorizontal(HorizontalAlignment h) {
  211. _halign = h;
  212. }
  213. void setAlignVertical(VerticalAlignment v) {
  214. _valign = v;
  215. }
  216. void setCoordinateMode(CoordinateMode cm) {
  217. _coordMode = cm;
  218. }
  219. void setCanFill(bool f) {
  220. _canFill = f;
  221. }
  222. void setCanClone(bool c) {
  223. _canClone = c;
  224. }
  225. WindowManager* getWindowManager() {
  226. return _getWindowManager();
  227. }
  228. const WindowManager* getWindowManager() const {
  229. return _getWindowManager();
  230. }
  231. Window* getParent() {
  232. return _parent;
  233. }
  234. const Window* getParent() const {
  235. return _parent;
  236. }
  237. unsigned int getIndex() const {
  238. return _index;
  239. }
  240. XYCoord getOrigin() const {
  241. return XYCoord(getX(), getY());
  242. }
  243. Color getImageColorAtXY(const XYCoord& xy) const {
  244. return getImageColorAtXY(xy.x(), xy.y());
  245. }
  246. Color getImageColorAtPointerXY(double x, double y) const {
  247. return getImageColorAtXY(localXY(x, y));
  248. }
  249. Point getPosition() const {
  250. return Point(getX(), getY(), getZ());
  251. }
  252. XYCoord getSize() const {
  253. return XYCoord(getWidth(), getHeight());
  254. }
  255. Quad getDimensions() const {
  256. return Quad(getX(), getY(), getWidth(), getHeight());
  257. }
  258. point_type getPadLeft() const {
  259. return _padLeft;
  260. }
  261. point_type getPadRight() const {
  262. return _padRight;
  263. }
  264. point_type getPadTop() const {
  265. return _padTop;
  266. }
  267. point_type getPadBottom() const {
  268. return _padBottom;
  269. }
  270. HorizontalAlignment getAlignHorizontal() const {
  271. return _halign;
  272. }
  273. VerticalAlignment getAlignVertical() const {
  274. return _valign;
  275. }
  276. CoordinateMode getCoordinateMode() const {
  277. return _coordMode;
  278. }
  279. bool canFill() const {
  280. return _canFill;
  281. }
  282. bool canClone() const {
  283. return _canClone;
  284. }
  285. // This casts the bool _fill variable to be used in iteratively in functions such
  286. // as Window::_accumulate and whatnot.
  287. point_type getFillAsNumeric() const {
  288. return static_cast<point_type>(_canFill);
  289. }
  290. point_type getWidthTotal() const {
  291. return getWidth() + getPadHorizontal();
  292. }
  293. point_type getHeightTotal() const {
  294. return getHeight() + getPadVertical();
  295. }
  296. point_type getMinWidth() const {
  297. return _minWidth;
  298. }
  299. point_type getMinHeight() const {
  300. return _minHeight;
  301. }
  302. point_type getMinWidthTotal() const {
  303. return _minWidth + getPadHorizontal();
  304. }
  305. point_type getMinHeightTotal() const {
  306. return _minHeight + getPadVertical();
  307. }
  308. unsigned int getLayer() const {
  309. return _layer;
  310. }
  311. protected:
  312. point_type _calculateZ(unsigned int) const;
  313. PointArray* _verts() {
  314. return dynamic_cast<PointArray*>(getVertexArray());
  315. }
  316. const PointArray* _verts() const {
  317. return dynamic_cast<const PointArray*>(getVertexArray());
  318. }
  319. ColorArray* _cols() {
  320. return dynamic_cast<ColorArray*>(getColorArray());
  321. }
  322. const ColorArray* _cols() const {
  323. return dynamic_cast<const ColorArray*>(getColorArray());
  324. }
  325. TexCoordArray* _texs() {
  326. return dynamic_cast<TexCoordArray*>(getTexCoordArray(0));
  327. }
  328. const TexCoordArray* _texs() const {
  329. return dynamic_cast<const TexCoordArray*>(getTexCoordArray(0));
  330. }
  331. osg::Texture* _texture() {
  332. osg::StateSet* ss = getStateSet();
  333. if(!ss) return 0;
  334. return dynamic_cast<osg::Texture2D*>(
  335. ss->getTextureAttribute(0, osg::StateAttribute::TEXTURE)
  336. );
  337. }
  338. const osg::Texture* _texture() const {
  339. const osg::StateSet* ss = getStateSet();
  340. if(!ss) return 0;
  341. return dynamic_cast<const osg::Texture2D*>(
  342. ss->getTextureAttribute(0, osg::StateAttribute::TEXTURE)
  343. );
  344. }
  345. osg::Image* _image() {
  346. return _getImage();
  347. }
  348. const osg::Image* _image() const {
  349. return _getImage();
  350. }
  351. friend class Window;
  352. // TODO: Because of the current class design, I don't think it's possible to
  353. // have a ref_ptr here. :(
  354. Window* _parent;
  355. unsigned int _index;
  356. unsigned int _layer;
  357. // Padding is the value of pixels of space between whatever the widget is "contianed"
  358. // in and the point at which it starts getting placed.
  359. point_type _padLeft;
  360. point_type _padRight;
  361. point_type _padTop;
  362. point_type _padBottom;
  363. // The alignments are used in conjunction when the widget is NOT set to fill.
  364. VerticalAlignment _valign;
  365. HorizontalAlignment _halign;
  366. // This flag determines how sizing values are interpretted by setDimensions().
  367. CoordinateMode _coordMode;
  368. // These are the relative values, which are not stored directly in our verts
  369. // array but kept around for calculation later.
  370. Quad _relCoords;
  371. // This fill flag determines whether or not the widget will resize itself to fill
  372. // all available space.
  373. bool _canFill;
  374. // Set this to false in an implementation to prevent copying.
  375. bool _canClone;
  376. // This variable is only used by the Window object to determine if it's necessary
  377. // to call managed().
  378. bool _isManaged;
  379. // This variable is like _isManaged; it is used to store whether the Widget has
  380. // been styled yet.
  381. bool _isStyled;
  382. // Set these variables to be the minimum size of a Widget so that it cannot be
  383. // resized any smaller than this.
  384. point_type _minWidth;
  385. point_type _minHeight;
  386. static osg::ref_ptr<PointArray> _norms;
  387. WindowManager* _getWindowManager () const;
  388. osg::Image* _getImage () const;
  389. };
  390. typedef std::list<osg::observer_ptr<Widget> > WidgetList;
  391. // A Widget subclass that prints stuff using osg::notify(). :)
  392. struct NotifyWidget: public Widget {
  393. META_Object(osgWidget, NotifyWidget);
  394. NotifyWidget(const std::string& n = "", point_type w = 0.0f, point_type h = 0.0f):
  395. Widget(n, w, h) {
  396. setEventMask(EVENT_ALL);
  397. }
  398. NotifyWidget(const NotifyWidget& widget, const osg::CopyOp& co):
  399. Widget(widget, co) {
  400. }
  401. bool focus(const WindowManager*) {
  402. osg::notify(osg::NOTICE) << _name << " > focus called" << std::endl;
  403. return false;
  404. }
  405. bool unfocus(const WindowManager*) {
  406. osg::notify(osg::NOTICE) << _name << " > unfocus called" << std::endl;
  407. return false;
  408. }
  409. bool mouseEnter(double, double, const WindowManager*) {
  410. osg::notify(osg::NOTICE) << _name << " > mouseEnter called" << std::endl;
  411. return false;
  412. }
  413. bool mouseOver(double, double, const WindowManager*) {
  414. osg::notify(osg::NOTICE) << _name << " > mouseOver called" << std::endl;
  415. return false;
  416. }
  417. bool mouseLeave(double, double, const WindowManager*) {
  418. osg::notify(osg::NOTICE) << _name << " > mouseLeave called" << std::endl;
  419. return false;
  420. }
  421. bool mouseDrag(double, double, const WindowManager*) {
  422. osg::notify(osg::NOTICE) << _name << " > mouseDrag called" << std::endl;
  423. return false;
  424. }
  425. bool mousePush(double, double, const WindowManager*) {
  426. osg::notify(osg::NOTICE) << _name << " > mousePush called" << std::endl;
  427. return false;
  428. }
  429. bool mouseRelease(double, double, const WindowManager*) {
  430. osg::notify(osg::NOTICE) << _name << " > mouseRelease called" << std::endl;
  431. return false;
  432. }
  433. bool mouseScroll(double, double, const WindowManager*) {
  434. osg::notify(osg::NOTICE) << _name << " > mouseScroll called" << std::endl;
  435. return false;
  436. }
  437. bool keyPress(int, int, const WindowManager*) {
  438. osg::notify(osg::NOTICE) << _name << " > keyPress called" << std::endl;
  439. return false;
  440. }
  441. bool keyRelease(int, int, const WindowManager*) {
  442. osg::notify(osg::NOTICE) << _name << " > keyRelease called" << std::endl;
  443. return false;
  444. }
  445. };
  446. // A Widget that eats all events and returns true.
  447. struct NullWidget: public Widget {
  448. META_Object(osgWidget, NullWidget);
  449. NullWidget(const std::string& n = "", point_type w = 0.0f, point_type h = 0.0f):
  450. Widget(n, w, h) {
  451. setEventMask(EVENT_ALL);
  452. }
  453. NullWidget(const NullWidget& widget, const osg::CopyOp& co):
  454. Widget(widget, co) {
  455. }
  456. bool focus(const WindowManager*) {
  457. return true;
  458. }
  459. bool unfocus(const WindowManager*) {
  460. return true;
  461. }
  462. bool mouseEnter(double, double, const WindowManager*) {
  463. return true;
  464. }
  465. bool mouseOver(double, double, const WindowManager*) {
  466. return true;
  467. }
  468. bool mouseLeave(double, double, const WindowManager*) {
  469. return true;
  470. }
  471. bool mouseDrag(double, double, const WindowManager*) {
  472. return true;
  473. }
  474. bool mousePush(double, double, const WindowManager*) {
  475. return true;
  476. }
  477. bool mouseRelease(double, double, const WindowManager*) {
  478. return true;
  479. }
  480. bool mouseScroll(double, double, const WindowManager*) {
  481. return true;
  482. }
  483. bool keyPress(int, int, const WindowManager*) {
  484. return true;
  485. }
  486. bool keyRelease(int, int, const WindowManager*) {
  487. return true;
  488. }
  489. };
  490. }
  491. #endif