tb_widgets.h 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  1. // ================================================================================
  2. // == This file is a part of Turbo Badger. (C) 2011-2014, Emil Segerås ==
  3. // == See tb_core.h for more information. ==
  4. // ================================================================================
  5. #ifndef TB_WIDGETS_H
  6. #define TB_WIDGETS_H
  7. #include "tb_core.h"
  8. #include "tb_geometry.h"
  9. #include "tb_skin.h"
  10. #include "tb_linklist.h"
  11. #include "tb_widget_value.h"
  12. #include "tb_object.h"
  13. #include "tb_font_desc.h"
  14. namespace tb {
  15. class TBWindow;
  16. class TBWidget;
  17. class TBFontFace;
  18. class TBScroller;
  19. class TBWidgetListener;
  20. class TBLongClickTimer;
  21. struct INFLATE_INFO;
  22. // == Generic widget stuff =================================================
  23. enum TB_ALIGN {
  24. TB_ALIGN_LEFT, ///< Align to the left side
  25. TB_ALIGN_TOP, ///< Align to the top (above)
  26. TB_ALIGN_RIGHT, ///< Align to the right side
  27. TB_ALIGN_BOTTOM ///< Align to the bottom (below)
  28. };
  29. enum EVENT_TYPE {
  30. /** Click event is what should be used to trig actions in almost all cases.
  31. It is invoked on a widget after POINTER_UP if the pointer is still inside
  32. its hit area. It can also be invoked by keyboard on some clickable widgets
  33. (see TBWidget::SetClickByKey).
  34. If panning of scrollable widgets start while the pointer is down, CLICK
  35. won't be invoked when releasing the pointer (since that should stop panning). */
  36. EVENT_TYPE_CLICK,
  37. /** Long click event is sent when the pointer has been down for some time
  38. without moving much.
  39. It is invoked on a widget that has enabled it (TBWidget::SetWantLongClick
  40. If this event isn't handled, the widget will invoke a CONTEXT_MENU event.
  41. If any of those are handled, the CLICK event that would normally be
  42. invoked after the pending POINTER_UP will be suppressed. */
  43. EVENT_TYPE_LONG_CLICK,
  44. EVENT_TYPE_POINTER_DOWN,
  45. EVENT_TYPE_POINTER_UP,
  46. EVENT_TYPE_POINTER_MOVE,
  47. EVENT_TYPE_RIGHT_POINTER_DOWN,
  48. EVENT_TYPE_RIGHT_POINTER_UP,
  49. EVENT_TYPE_WHEEL,
  50. /** Invoked after changing text in a TBTextField, changing selected item
  51. in a TBSelectList etc. Invoking this event trigs synchronization with
  52. connected TBWidgetValue and other widgets connected to it. */
  53. EVENT_TYPE_CHANGED,
  54. EVENT_TYPE_KEY_DOWN,
  55. EVENT_TYPE_KEY_UP,
  56. /** Invoked by the platform when a standard keyboard shortcut is pressed.
  57. It's called before InvokeKeyDown (EVENT_TYPE_KEY_DOWN) and if the event
  58. is handled (returns true), the KeyDown is canceled.
  59. The ref_id will be set to one of the following:
  60. "cut", "copy", "paste", "selectall", "undo", "redo", "new", "open", "save". */
  61. EVENT_TYPE_SHORTCUT,
  62. /** Invoked when a context menu should be opened at the event x and y coordinates.
  63. It may be invoked automatically for a widget on long click, if nothing handles
  64. the long click event. */
  65. EVENT_TYPE_CONTEXT_MENU,
  66. /** Invoked by the platform when one or multiple files has been dropped on
  67. the widget. The event is guaranteed to be a TBWidgetEventFileDrop. */
  68. EVENT_TYPE_FILE_DROP,
  69. /** Invoked by the platform when a tab container's tab changed */
  70. EVENT_TYPE_TAB_CHANGED,
  71. /** Custom event. Not used internally. ref_id may be used for additional type info. */
  72. EVENT_TYPE_CUSTOM,
  73. /** Turbobadger implementation for touch events */
  74. EVENT_TYPE_TOUCH_DOWN,
  75. EVENT_TYPE_TOUCH_UP,
  76. EVENT_TYPE_TOUCH_MOVE,
  77. EVENT_TYPE_TOUCH_CANCEL
  78. };
  79. enum MODIFIER_KEYS {
  80. TB_MODIFIER_NONE = 0,
  81. TB_CTRL = 1,
  82. TB_SHIFT = 2,
  83. TB_ALT = 4,
  84. TB_SUPER = 8
  85. };
  86. MAKE_ENUM_FLAG_COMBO(MODIFIER_KEYS);
  87. enum SPECIAL_KEY
  88. {
  89. TB_KEY_UNDEFINED = 0,
  90. TB_KEY_UP, TB_KEY_DOWN, TB_KEY_LEFT, TB_KEY_RIGHT,
  91. TB_KEY_PAGE_UP, TB_KEY_PAGE_DOWN, TB_KEY_HOME, TB_KEY_END,
  92. TB_KEY_TAB, TB_KEY_BACKSPACE, TB_KEY_INSERT, TB_KEY_DELETE,
  93. TB_KEY_ENTER, TB_KEY_ESC,
  94. TB_KEY_F1, TB_KEY_F2, TB_KEY_F3, TB_KEY_F4, TB_KEY_F5, TB_KEY_F6,
  95. TB_KEY_F7, TB_KEY_F8, TB_KEY_F9, TB_KEY_F10, TB_KEY_F11, TB_KEY_F12
  96. };
  97. class TBWidgetEvent : public TBTypedObject
  98. {
  99. public:
  100. TBWidget *target; ///< The widget that invoked the event
  101. EVENT_TYPE type; ///< Which type of event
  102. int target_x; ///< X position in target widget. Set for all pointer events, click and wheel.
  103. int target_y; ///< Y position in target widget. Set for all pointer events, click and wheel.
  104. int delta_x; ///< Set for EVENT_TYPE_WHEEL. Positive is a turn right.
  105. int delta_y; ///< Set for EVENT_TYPE_WHEEL. Positive is a turn against the user.
  106. int count; ///< 1 for all events, but increased for POINTER_DOWN event to 2 for doubleclick, 3 for tripleclick and so on.
  107. int key;
  108. SPECIAL_KEY special_key;
  109. MODIFIER_KEYS modifierkeys;
  110. TBID ref_id; ///< Sometimes (when documented) events have a ref_id (The id that caused this event)
  111. bool touch; ///< Set for pointer events. True if the event is a touch event (finger or pen on screen)
  112. ///< False if mouse or other cursor input.
  113. TBOBJECT_SUBCLASS(TBWidgetEvent, TBTypedObject);
  114. TBWidgetEvent(EVENT_TYPE type) : target(nullptr), type(type), target_x(0), target_y(0), delta_x(0), delta_y(0), count(1),
  115. key(0), special_key(TB_KEY_UNDEFINED), modifierkeys(TB_MODIFIER_NONE), touch(false) {}
  116. TBWidgetEvent(EVENT_TYPE type, int x, int y, bool touch, MODIFIER_KEYS modifierkeys = TB_MODIFIER_NONE) :
  117. target(nullptr), type(type), target_x(x), target_y(y), delta_x(0), delta_y(0),
  118. count(1), key(0), special_key(TB_KEY_UNDEFINED), modifierkeys(modifierkeys),
  119. touch(touch) {}
  120. /** The count value may be 1 to infinity. If you f.ex want to see which count it is for something
  121. handling click and double click, call GetCountCycle(2). If you also handle triple click, call
  122. GetCountCycle(3) and so on. That way you'll get a count that always cycle in the range you need. */
  123. int GetCountCycle(int max) { return ((count - 1) % max) + 1; }
  124. bool IsPointerEvent() const { return type == EVENT_TYPE_POINTER_DOWN ||
  125. type == EVENT_TYPE_POINTER_UP ||
  126. type == EVENT_TYPE_POINTER_MOVE; }
  127. bool IsTouchEvent() const { return type == EVENT_TYPE_TOUCH_DOWN ||
  128. type == EVENT_TYPE_TOUCH_UP ||
  129. type == EVENT_TYPE_TOUCH_MOVE ||
  130. type == EVENT_TYPE_TOUCH_CANCEL; }
  131. bool IsKeyEvent() const { return type == EVENT_TYPE_KEY_DOWN ||
  132. type == EVENT_TYPE_KEY_UP; }
  133. };
  134. /** TBWidgetEventFileDrop is a event of type EVENT_TYPE_FILE_DROP.
  135. It contains a list of filenames of the files that was dropped. */
  136. class TBWidgetEventFileDrop : public TBWidgetEvent
  137. {
  138. public:
  139. TBListAutoDeleteOf<TBStr> files;
  140. TBOBJECT_SUBCLASS(TBWidgetEventFileDrop, TBWidgetEvent);
  141. TBWidgetEventFileDrop() : TBWidgetEvent(EVENT_TYPE_FILE_DROP) {}
  142. };
  143. /** TBWidget state types (may be combined).
  144. NOTE: This should exactly match SKIN_STATE in tb_skin.h! */
  145. enum WIDGET_STATE {
  146. WIDGET_STATE_NONE = 0,
  147. WIDGET_STATE_DISABLED = 1,
  148. WIDGET_STATE_FOCUSED = 2,
  149. WIDGET_STATE_PRESSED = 4,
  150. WIDGET_STATE_SELECTED = 8,
  151. WIDGET_STATE_HOVERED = 16,
  152. WIDGET_STATE_ALL = WIDGET_STATE_DISABLED |
  153. WIDGET_STATE_FOCUSED |
  154. WIDGET_STATE_PRESSED |
  155. WIDGET_STATE_SELECTED |
  156. WIDGET_STATE_HOVERED
  157. };
  158. MAKE_ENUM_FLAG_COMBO(WIDGET_STATE);
  159. /** TBWidget gravity (may be combined).
  160. Gravity gives hints about positioning and sizing preferences. */
  161. enum WIDGET_GRAVITY {
  162. WIDGET_GRAVITY_NONE = 0,
  163. WIDGET_GRAVITY_LEFT = 1,
  164. WIDGET_GRAVITY_RIGHT = 2,
  165. WIDGET_GRAVITY_TOP = 4,
  166. WIDGET_GRAVITY_BOTTOM = 8,
  167. WIDGET_GRAVITY_LEFT_RIGHT = WIDGET_GRAVITY_LEFT | WIDGET_GRAVITY_RIGHT,
  168. WIDGET_GRAVITY_TOP_BOTTOM = WIDGET_GRAVITY_TOP | WIDGET_GRAVITY_BOTTOM,
  169. WIDGET_GRAVITY_ALL = WIDGET_GRAVITY_LEFT_RIGHT | WIDGET_GRAVITY_TOP_BOTTOM,
  170. WIDGET_GRAVITY_DEFAULT = WIDGET_GRAVITY_LEFT | WIDGET_GRAVITY_TOP
  171. };
  172. MAKE_ENUM_FLAG_COMBO(WIDGET_GRAVITY);
  173. enum AXIS {
  174. AXIS_X, ///< Horizontal layout
  175. AXIS_Y, ///< Vertical layout
  176. };
  177. /** Defines how the size in one axis depend on the other axis when a widgets size is
  178. affected by constraints. */
  179. enum SIZE_DEP {
  180. /** No dependency (Faster layout). */
  181. SIZE_DEP_NONE = 0,
  182. /** The width is dependant on the height. Additional layout pass may be required. */
  183. SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT = 1,
  184. /** The height is dependant on the width. Additional layout pass may be required. */
  185. SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH = 2,
  186. /** Both width and height are dependant on each other. Additional layout pass may
  187. be required. */
  188. SIZE_DEP_BOTH = SIZE_DEP_WIDTH_DEPEND_ON_HEIGHT |
  189. SIZE_DEP_HEIGHT_DEPEND_ON_WIDTH
  190. };
  191. MAKE_ENUM_FLAG_COMBO(SIZE_DEP);
  192. /** PreferredSize contains size preferences for a TBWidget.
  193. This is calculated during layout for each widget from
  194. the current skin, widget preferences and LayoutParams. */
  195. class PreferredSize
  196. {
  197. public:
  198. PreferredSize() : min_w(0), min_h(0)
  199. , max_w(10000), max_h(10000)
  200. , pref_w(0), pref_h(0)
  201. , size_dependency(SIZE_DEP_NONE) {}
  202. PreferredSize(int w, int h) : min_w(w), min_h(h)
  203. , max_w(w), max_h(h)
  204. , pref_w(w), pref_h(h)
  205. , size_dependency(SIZE_DEP_NONE) {}
  206. int min_w, min_h; ///< The minimal preferred width and height.
  207. int max_w, max_h; ///< The maximum preferred width and height.
  208. int pref_w, pref_h; ///< The preferred width and height.
  209. SIZE_DEP size_dependency; ///< The size dependency when size is affected by constraints.
  210. };
  211. /** LayoutParams defines size preferences for a TBWidget that
  212. are set on the widget to override size preferences from
  213. skin and widget. */
  214. class LayoutParams
  215. {
  216. public:
  217. static const int UNSPECIFIED = TB_INVALID_DIMENSION;
  218. LayoutParams() : min_w(UNSPECIFIED), min_h(UNSPECIFIED)
  219. , max_w(UNSPECIFIED), max_h(UNSPECIFIED)
  220. , pref_w(UNSPECIFIED), pref_h(UNSPECIFIED) {}
  221. /** Set both min max and preferred width to the given width. */
  222. void SetWidth(int width) { min_w = max_w = pref_w = width; }
  223. /** Set both min max and preferred height to the given height. */
  224. void SetHeight(int height) { min_h = max_h = pref_h = height; }
  225. int min_w, min_h; ///< The minimal preferred width and height.
  226. int max_w, max_h; ///< The maximum preferred width and height.
  227. int pref_w, pref_h; ///< The preferred width and height.
  228. };
  229. /** Specifies size constraints used during size calculations. */
  230. class SizeConstraints
  231. {
  232. public:
  233. static const int NO_RESTRICTION = 10000;
  234. /** The available width and height. May be NO_RESTRICTION which is a large value. */
  235. int available_w, available_h;
  236. /** Constrain to the given width and height. */
  237. SizeConstraints(int w, int h) : available_w(w), available_h(h) {}
  238. /** No constraints. */
  239. SizeConstraints() : available_w(NO_RESTRICTION), available_h(NO_RESTRICTION) {}
  240. /** Return new constraints reduced by the given padding. */
  241. SizeConstraints ConstrainByPadding(int horizontal_padding, int vertical_padding) const
  242. {
  243. return SizeConstraints(available_w == NO_RESTRICTION ? NO_RESTRICTION : available_w - horizontal_padding,
  244. available_h == NO_RESTRICTION ? NO_RESTRICTION : available_h - vertical_padding);
  245. }
  246. /** Return new constraints that are constrained by LayoutParams. */
  247. SizeConstraints ConstrainByLayoutParams(const LayoutParams &lp) const
  248. {
  249. return SizeConstraints(ConstrainByLPMax(available_w, lp.min_w, lp.max_w),
  250. ConstrainByLPMax(available_h, lp.min_h, lp.max_h));
  251. }
  252. bool operator == (const SizeConstraints &sc) const { return available_w == sc.available_w &&
  253. available_h == sc.available_h; }
  254. private:
  255. int ConstrainByLPMax(int constraint, int lp_min, int lp_max) const
  256. {
  257. if (constraint == NO_RESTRICTION)
  258. return lp_max != LayoutParams::UNSPECIFIED ? lp_max : NO_RESTRICTION;
  259. int ret = constraint;
  260. if (lp_min != LayoutParams::UNSPECIFIED)
  261. ret = MAX(ret, lp_min);
  262. if (lp_max != LayoutParams::UNSPECIFIED)
  263. ret = MIN(ret, lp_max);
  264. return ret;
  265. }
  266. };
  267. /** Defines widget z level, used with TBWidget::SetZ, TBWidget::AddChild. */
  268. enum WIDGET_Z {
  269. WIDGET_Z_TOP, ///< The toplevel (Visually drawn on top of everything else).
  270. WIDGET_Z_BOTTOM ///< The bottomlevel (Visually drawn behind everything else).
  271. };
  272. /** Defines widget z level relative to another widget, used with TBWidget::AddChildRelative. */
  273. enum WIDGET_Z_REL {
  274. WIDGET_Z_REL_BEFORE, ///< Before the reference widget (visually behind reference).
  275. WIDGET_Z_REL_AFTER ///< After the reference widget (visually above reference).
  276. };
  277. /** Defines widget visibility, used with TBWidget::SetVisibility. */
  278. enum WIDGET_VISIBILITY {
  279. WIDGET_VISIBILITY_VISIBLE, ///< Visible (default)
  280. WIDGET_VISIBILITY_INVISIBLE, ///< Invisible, but layouted. Interaction disabled.
  281. WIDGET_VISIBILITY_GONE ///< Invisible and no layout. Interaction disabled.
  282. };
  283. enum WIDGET_INVOKE_INFO {
  284. WIDGET_INVOKE_INFO_NORMAL,
  285. WIDGET_INVOKE_INFO_NO_CALLBACKS
  286. };
  287. enum WIDGET_FOCUS_REASON {
  288. WIDGET_FOCUS_REASON_NAVIGATION, ///< Set focus by navigation (i.e. keyboard tab). This will
  289. ///< scroll to the widget if needed.
  290. WIDGET_FOCUS_REASON_POINTER, ///< Set focus by pointer (i.e. clicking)
  291. WIDGET_FOCUS_REASON_UNKNOWN ///< Set focus by anything else.
  292. };
  293. /** Hit status return value for TBWidget::GetHitStatus */
  294. enum WIDGET_HIT_STATUS {
  295. WIDGET_HIT_STATUS_NO_HIT = 0, ///< The widget was not hit
  296. WIDGET_HIT_STATUS_HIT, ///< The widget was hit, any child may be hit too.
  297. WIDGET_HIT_STATUS_HIT_NO_CHILDREN ///< The widget was hit, no children should be hit.
  298. };
  299. // ATOMIC BEGIN: this must only be used by UIWidget, as we are casting to it
  300. class TBWidgetDelegate
  301. {
  302. public:
  303. virtual bool OnEvent(const TBWidgetEvent &ev) = 0;
  304. virtual void OnFocusChanged(bool focused) = 0;
  305. virtual void OnDelete() = 0;
  306. virtual void OnResized(int old_w, int old_h) = 0;
  307. };
  308. // ATOMIC END
  309. /** The base TBWidget class.
  310. Make a subclass to implement UI controls.
  311. Each widget has a background skin (no skin specified by default) which will be used to
  312. calculate the default size preferences and padding around the preferred content size.
  313. Note: When you subclass a widget, use the TBOBJECT_SUBCLASS macro to define the type
  314. casting functions instead of implementing those manually. */
  315. class TBWidget : public TBTypedObject, public TBLinkOf<TBWidget>
  316. {
  317. public:
  318. // For safe typecasting
  319. TBOBJECT_SUBCLASS(TBWidget, TBTypedObject);
  320. TBWidget();
  321. virtual ~TBWidget();
  322. /** Set the rect for this widget in its parent. The rect is relative to the parent widget.
  323. The skin may expand outside this rect to draw f.ex shadows. */
  324. void SetRect(const TBRect &rect);
  325. inline TBRect GetRect() const { return m_rect; }
  326. /** Set position of this widget in its parent. The position is relative to the parent widget. */
  327. void SetPosition(const TBPoint &pos) { SetRect(TBRect(pos.x, pos.y, m_rect.w, m_rect.h)); }
  328. /** Set size of this widget. */
  329. void SetSize(int width, int height) { SetRect(TBRect(m_rect.x, m_rect.y, width, height)); }
  330. /** Invalidate should be called if the widget need to be repainted,
  331. to make sure the renderer repaints it and its children next frame. */
  332. void Invalidate();
  333. /** Call if something changes that might need other widgets to update their state.
  334. F.ex if a action availability changes, some widget might have to become enabled/disabled.
  335. Calling this will result in a later call to OnProcessStates().
  336. This is done automatically for all invoked events of type:
  337. EVENT_TYPE_CLICK, EVENT_TYPE_LONG_CLICK, EVENT_TYPE_CHANGED, EVENT_TYPE_KEYDOWN,
  338. EVENT_TYPE_KEYUP. */
  339. void InvalidateStates();
  340. /** Call if something changes that might cause any skin to change due to different state
  341. or conditions. This is called automatically from InvalidateStates(), when event
  342. EVENT_TYPE_CHANGED is invoked, and in various other situations. */
  343. void InvalidateSkinStates();
  344. /** Delete the widget with the possibility for some extended life during animations.
  345. If any widget listener responds true to OnWidgetDying it will be kept as a child and live
  346. until the animations are done, but the widgets and all its children are marked as dying.
  347. Dying widgets get no input or focus.
  348. If no widget listener responded, it will be deleted immediately. */
  349. void Die();
  350. /** Return true if this widget or any of its parents is dying. */
  351. bool GetIsDying() const { return m_packed.is_dying || (m_parent && m_parent->GetIsDying()); }
  352. /** Set the id reference for this widgets. This id is 0 by default.
  353. You can use this id to receive the widget from GetWidgetByID (or
  354. preferable TBSafeGetByID to avoid dangerous casts). */
  355. void SetID(const TBID &id);
  356. TBID &GetID() { return m_id; }
  357. /** Set the group id reference for this widgets. This id is 0 by default.
  358. All widgets with the same group id under the same group root will
  359. be automatically changed when one change its value. */
  360. void SetGroupID(const TBID &id) { m_group_id = id; }
  361. TBID &GetGroupID() { return m_group_id; }
  362. /** Get this widget or any child widget with a matching id, or nullptr if none is found. */
  363. TBWidget *GetWidgetByID(const TBID &id) { return GetWidgetByIDInternal(id); }
  364. /** Get this widget or any child widget with a matching id and type, or nullptr if none is found. */
  365. template<class T> T *GetWidgetByIDAndType(const TBID &id)
  366. { return (T*) GetWidgetByIDInternal(id, GetTypeId<T>()); }
  367. /** Enable or disable the given state(s). The state affects which skin state is used when drawing.
  368. Some states are set automatically on interaction. See GetAutoState(). */
  369. void SetState(WIDGET_STATE state, bool on);
  370. /** Get status of the given state(s). Returns true if the given state combination is set. */
  371. bool GetState(WIDGET_STATE state) const { return (m_state & state) ? true : false; }
  372. /** Set the widget state. Like SetState but setting the entire state as given, instead
  373. of toggling individual states. See SetState for more info on states. */
  374. void SetStateRaw(WIDGET_STATE state);
  375. /** Get the widget state. */
  376. WIDGET_STATE GetStateRaw() const { return m_state; }
  377. /** Return the current combined state for this widget. It will also add some
  378. automatic states, such as hovered (if the widget is currently hovered), or pressed etc.
  379. Automatic states: WIDGET_STATE_PRESSED, WIDGET_STATE_HOVERED, WIDGET_STATE_FOCUSED.
  380. Remarks for WIDGET_STATE_FOCUSED: May also be controlled by calling SetAutoFocusState and
  381. the define TB_ALWAYS_SHOW_EDIT_FOCUS. */
  382. WIDGET_STATE GetAutoState() const;
  383. /** Set if the state WIDGET_STATE_FOCUSED should be set automatically for the focused widget.
  384. This value is set to true when moving focus by keyboard, and set to off when clicking
  385. with the pointer. */
  386. static void SetAutoFocusState(bool on);
  387. /** Set opacity for this widget and its children from 0.0 - 1.0.
  388. If opacity is 0 (invisible), the widget won't receive any input. */
  389. void SetOpacity(float opacity);
  390. float GetOpacity() const { return m_opacity; }
  391. /** Set opacity for this widget and its children from 0.0 - 1.0 when in WIDGET_STATE_DISABLED.
  392. If disabled opacity is < 0, default skin opacity will be used.
  393. If opacity is 0 (invisible), the widget won't receive any input. */
  394. void SetDisabledOpacity(float opacity);
  395. float GetDisabledOpacity() const { return m_disabledOpacity; }
  396. /** Set visibility for this widget and its children.
  397. If visibility is not WIDGET_VISIBILITY_VISIBLE, the widget won't receive any input. */
  398. void SetVisibilility(WIDGET_VISIBILITY vis);
  399. WIDGET_VISIBILITY GetVisibility() const;
  400. /** Return true if this widget and all its ancestors are visible
  401. (has a opacity > 0 and visibility WIDGET_VISIBILITY_VISIBLE) */
  402. bool GetVisibilityCombined() const;
  403. /** Return true if this widget or any of its parents are disabled (has state WIDGET_STATE_DISABLED). */
  404. bool GetDisabled() const;
  405. /** Add the child to this widget. The child widget will automatically be deleted when
  406. this widget is deleted. (If the child isn't removed again with RemoveChild.) */
  407. void AddChild(TBWidget *child, WIDGET_Z z = WIDGET_Z_TOP, WIDGET_INVOKE_INFO info = WIDGET_INVOKE_INFO_NORMAL);
  408. /** Add the child to this widget. See AddChild for adding a child to the top or bottom.
  409. This takes a relative Z and insert the child before or after the given reference widget.*/
  410. void AddChildRelative(TBWidget *child, WIDGET_Z_REL z, TBWidget *reference, WIDGET_INVOKE_INFO info = WIDGET_INVOKE_INFO_NORMAL);
  411. /** Remove child from this widget without deleting it. */
  412. void RemoveChild(TBWidget *child, WIDGET_INVOKE_INFO info = WIDGET_INVOKE_INFO_NORMAL);
  413. /** Remove and delete all children in this widget.
  414. Note: This won't invoke Die so there's no chance for widgets to survive or
  415. animate. They will be instantly removed and deleted. */
  416. void DeleteAllChildren();
  417. /** Sets the z-order of this widget related to its siblings. When a widget is added with AddChild, it will be
  418. placed at the top in the parent (Above previously added widget). SetZ can be used to change the order. */
  419. void SetZ(WIDGET_Z z);
  420. /** Set the z order in which children are added during resource loading. */
  421. void SetZInflate(WIDGET_Z z) { m_packed.inflate_child_z = z; }
  422. WIDGET_Z GetZInflate() const { return (WIDGET_Z) m_packed.inflate_child_z; }
  423. /** Set the widget gravity (any combination of WIDGET_GRAVITY).
  424. For child widgets in a layout, the gravity affects how the layout is done depending on the layout settings.
  425. For child widgets in a non layout widget, it will do some basic resizing/moving:
  426. -left && right: Widget resize horizontally when parent resize.
  427. -!left && right: Widget follows the right edge when parent resize.
  428. -top && bottom: Widget resize vertically when parent resize.
  429. -!top && bottom: Widget follows the bottom edge when parent resize. */
  430. void SetGravity(WIDGET_GRAVITY g);
  431. WIDGET_GRAVITY GetGravity() const { return m_gravity; }
  432. /** Set the skin background for this widget and call OnSkinChanged if it changed.
  433. The skin background is used for calculating padding, preferred size
  434. etc. if the widget doesn't have any preferences itself.
  435. The skin will be painted according to the current widget state (WIDGET_STATE).
  436. If there is no special skin state for WIDGET_STATE_FOCUSED, it will paint the skin
  437. element called "generic_focus" (if it exist) after painting all widget children.
  438. It's possible to omit the OnSkinChanged callback using WIDGET_INVOKE_INFO_NO_CALLBACKS. */
  439. void SetSkinBg(const TBID &skin_bg, WIDGET_INVOKE_INFO info = WIDGET_INVOKE_INFO_NORMAL);
  440. /** Return the current skin background, as set by SetSkinBg. */
  441. TBID GetSkinBg() const { return m_skin_bg; }
  442. /** Return the skin background element, or nullptr. */
  443. TBSkinElement *GetSkinBgElement();
  444. /** Set if this widget is a group root. Grouped widgets (such as TBRadioButton) will toggle all other
  445. widgets with the same group_id under the nearest parent group root. TBWindow is a group root by default. */
  446. void SetIsGroupRoot(bool group_root) { m_packed.is_group_root = group_root; }
  447. bool GetIsGroupRoot() const { return m_packed.is_group_root; }
  448. /** Set if this widget should be able to receive focus or not. */
  449. void SetIsFocusable(bool focusable) { m_packed.is_focusable = focusable; }
  450. bool GetIsFocusable() const { return m_packed.is_focusable; }
  451. /** Set if this widget should emulate a click when it's focused and pressing enter or space. */
  452. void SetClickByKey(bool click_by_key) { m_packed.click_by_key = click_by_key; }
  453. bool GetClickByKey() const { return m_packed.click_by_key; }
  454. /** Set if this widget should generate long-click event (or context menu event if nothing
  455. handles the long click event). The default is false. */
  456. void SetWantLongClick(bool want_long_click) { m_packed.want_long_click = want_long_click; }
  457. bool GetWantLongClick() const { return m_packed.want_long_click; }
  458. /** Set if this widget should ignore input, as if it didn't exist. */
  459. void SetIgnoreInput(bool ignore_input) { m_packed.ignore_input = ignore_input; }
  460. bool GetIgnoreInput() const { return m_packed.ignore_input; }
  461. /** Get if this widget wants interaction depending on various states.
  462. Cares about zero opacity, visibility, flag set by SetIgnoreInput, disabled state,
  463. and if the widget is currently dying. */
  464. bool GetIsInteractable() const;
  465. /** Set this widget to be the focused widget. It will be the one receiving keyboard input.
  466. Widgets can be focused only after enabling it (See SetIsFocusable(true)).
  467. Invisible or disabled widgets can not be focused.
  468. If SetFocus is called on a widget in a inactive window, it will succeed (return true),
  469. but it won't actually become focused until that window is activated (See TBWindow::SetLastFocus).
  470. Returns true if successfully focused, or if set as last focus in its window. */
  471. bool SetFocus(WIDGET_FOCUS_REASON reason, WIDGET_INVOKE_INFO info = WIDGET_INVOKE_INFO_NORMAL);
  472. bool GetIsFocused() const { return focused_widget == this; }
  473. /** Call SetFocus on all children and their children, until a widget is found that accepts it.
  474. Returns true if some child was successfully focused. */
  475. bool SetFocusRecursive(WIDGET_FOCUS_REASON reason);
  476. /** Move focus from the currently focused widget to another focusable widget. It will search
  477. for a focusable widget in the same TBWindow (or top root if there is no window) forward or
  478. backwards in the widget order. */
  479. bool MoveFocus(bool forward);
  480. /** Returns the child widget that contains the coordinate or nullptr if no one does. If include_children
  481. is true, the search will recurse into the childrens children. */
  482. TBWidget *GetWidgetAt(int x, int y, bool include_children) const;
  483. /** Get the child at the given index, or nullptr if there was no child at that index.
  484. Note: Avoid calling this in loops since it does iteration. Consider iterating
  485. the widgets directly instead! */
  486. TBWidget *GetChildFromIndex(int index) const;
  487. /** Get the child index of the given widget (that must be a child of this widget).
  488. Note: Avoid calling this in loops since it does iteration. Consider iterating
  489. the widgets directly instead! */
  490. int GetIndexFromChild(TBWidget *child) const;
  491. /** Get the text of a child widget with the given id, or an empty string if there was
  492. no widget with that id. */
  493. TBStr GetTextByID(const TBID &id);
  494. /** Get the value of a child widget with the given id, or 0 if there was no widget
  495. with that id. */
  496. int GetValueByID(const TBID &id);
  497. TBWidget *GetNextDeep(const TBWidget *bounding_ancestor = nullptr) const;
  498. TBWidget *GetPrevDeep() const;
  499. TBWidget *GetLastLeaf() const;
  500. inline TBWidget *GetFirstChild() const { return m_children.GetFirst(); }
  501. inline TBWidget *GetLastChild() const { return m_children.GetLast(); }
  502. TBLinkListOf<TBWidget>::Iterator GetIteratorForward() { return m_children.IterateForward(); }
  503. TBLinkListOf<TBWidget>::Iterator GetIteratorBackward() { return m_children.IterateBackward(); }
  504. // ATOMIC BEGIN
  505. /** Returns the number of children this widget contains. */
  506. int numChildren();
  507. /// searches for specified widget ID from the top of the widget tree, returns the 1st one found.
  508. TBWidget *FindWidget ( TBID searchid );
  509. /// print out the widget tree to stdout
  510. void PrintPretty( TBStr indent, bool last);
  511. /// return all of the widgets of the specified classname
  512. void SearchWidgetClass ( TBStr className, TBValue &results );
  513. /// return all of the widgets of the specified id
  514. void SearchWidgetId ( TBID searchid, TBValue &results );
  515. /// return all of the widgets with the specified text
  516. void SearchWidgetText ( TBStr searchText, TBValue &results );
  517. // ATOMIC END
  518. /** Return true if this widget is the same or a ancestor of other_widget. */
  519. bool IsAncestorOf(TBWidget *other_widget) const;
  520. /** Return true if this widget is the same as other_widget or if other_widget
  521. events are going through this widget (See GetEventDestination()) */
  522. bool IsEventDestinationFor(TBWidget *other_widget) const;
  523. TBWidgetDelegate* GetDelegate() {return m_delegate; }
  524. void SetDelegate(TBWidgetDelegate* delegate) { m_delegate = delegate; }
  525. // == Callbacks ==============================================
  526. /** Add a listener to this widget. It should be removed again with
  527. RemoveListener before the widget is deleted. */
  528. void AddListener(TBWidgetListener *listener);
  529. void RemoveListener(TBWidgetListener *listener);
  530. bool HasListener(TBWidgetListener *listener) const;
  531. /** Callback for handling events.
  532. Return true if the event is handled and should not
  533. continue to be handled by any parent widgets. */
  534. virtual bool OnEvent(const TBWidgetEvent &ev) { if (m_delegate) return m_delegate->OnEvent(ev); return false; }
  535. /** Callback for doing anything that might be needed before paint.
  536. F.ex Updating invalid layout, formatting text etc. */
  537. virtual void OnProcess() {}
  538. /** Callback for doing anything that might be needed before paint.
  539. This is called after OnProcess has been called on this widgets children. */
  540. virtual void OnProcessAfterChildren() {}
  541. /** Callback for doing state updates that depend on your application state.
  542. F.ex setting the disabled state on a widget which action is currently not
  543. available. This callback is called for all widgets before OnProcess if
  544. something has called InvalidateStates().*/
  545. virtual void OnProcessStates() {}
  546. /** PaintProps contains properties needed for painting a widget.
  547. Properties may be inherited from the parent widget if not specified
  548. in the skin. */
  549. class PaintProps
  550. {
  551. public:
  552. PaintProps();
  553. /** Text color as specified in the skin element, or inherited from parent. */
  554. TBColor text_color;
  555. };
  556. /** Callback for painting this widget.
  557. The skin is already painted and the opacity set to reflect this widgets.
  558. This is only called for widgets with a opacity > 0 */
  559. virtual void OnPaint(const PaintProps &paint_props) {}
  560. /** Callback for painting child widgets.
  561. The default implementation is painting all children. */
  562. virtual void OnPaintChildren(const PaintProps &paint_props);
  563. /** Callback for when this widget or any of its children have
  564. called Invalidate() */
  565. virtual void OnInvalid() {}
  566. /** Called when the background skin changes by calling SetSkinBg(), or when the skin
  567. has changed indirectly after a skin condition changes in a way that may affect layout.
  568. For indirect skin changes, OnSkinChanged is called before validation of layouts is about
  569. to happen in InvokeProcess().
  570. */
  571. virtual void OnSkinChanged() {}
  572. /** Called when the font has changed. */
  573. virtual void OnFontChanged() {}
  574. /** Called when the focus has changed. */
  575. virtual void OnFocusChanged(bool focused) { if (m_delegate) return m_delegate->OnFocusChanged(focused); }
  576. /** Called when the visibility has changed.
  577. Note: This is not called when combined visibility change, so it may change visibility
  578. because of ancestors without this being called. */
  579. virtual void OnVisibilityChanged() {}
  580. /** Called when the capture has changed. */
  581. virtual void OnCaptureChanged(bool captured) { SetCaptured(captured); }
  582. /** Called when a child widget has been added to this widget (before calling OnAdded on child). */
  583. virtual void OnChildAdded(TBWidget *child) {}
  584. /** Called when a child widget is about to be removed from this widget (before calling OnRemove on child). */
  585. virtual void OnChildRemove(TBWidget *child) {}
  586. /** Called when this widget has been added to a parent (after calling OnChildAdded on parent). */
  587. virtual void OnAdded() {}
  588. /** Called when a this widget has been removed from its parent (after calling OnChildRemove on parent). */
  589. virtual void OnRemove() {}
  590. /** Called when Die() is called on this widget. Note: Not called for children to the widget Die() was
  591. invoked on even though they are also dying. */
  592. virtual void OnDie() {}
  593. /** Called when this widget has been resized.
  594. The default implementation move and resize all children according to their gravity. */
  595. virtual void OnResized(int old_w, int old_h);
  596. /** Called when this widget has been scrolled. */
  597. virtual void OnScroll(int scroll_x, int scroll_y) {}
  598. /** Called just after a child has been inflated into this widget.
  599. The default implementation will resize the child to it's preferred size
  600. and position it according to the gravity. If you implement a layouting
  601. widget, you should override this to prevent doing unnecessary measuring. */
  602. virtual void OnInflateChild(TBWidget *child);
  603. /** Called when this widget is inflated from resources, before any children
  604. has been inflated. This will read generic widget properties and add the
  605. widget to the hierarchy if it's not already added. If overridden, you
  606. must call the super implementation. */
  607. virtual void OnInflate(const INFLATE_INFO &info);
  608. /** Get hit status tests if this widget should be hit at the given coordinate.
  609. The default implementation checks the visibility, ignored input flag, rectangle,
  610. and disabled status. */
  611. virtual WIDGET_HIT_STATUS GetHitStatus(int x, int y);
  612. /** Get if skin condition applies to this widget. This is called when a skin condition has the property
  613. PROPERTY_CUSTOM (not a generic one known by skin and the default widget condition context).
  614. This can be used to extend the skin conditions support with properties specific to different widgets. */
  615. virtual bool GetCustomSkinCondition(const TBSkinCondition::CONDITION_INFO &info) { return false; }
  616. /** Get this widget or a child widget that should be root for other children. This is useful
  617. for widgets having multiple children by default, to specify which one that should get the children. */
  618. virtual TBWidget *GetContentRoot() { return this; }
  619. /** Get this widget or a parent widget that is the absolute root parent
  620. if view_root is true, will return the widget for the UIView attached to root widget */
  621. TBWidget *GetParentRoot(bool view_root = true);
  622. /** Get the closest parent widget that is a TBWindow or nullptr if there is none.
  623. If this widget is a window itself, this will be returned. */
  624. TBWindow *GetParentWindow();
  625. /** Get the parent widget, or nullptr if this widget is not added. */
  626. inline TBWidget *GetParent() const { return m_parent; }
  627. /** Get the widget that should receive the events this widget invoke. By default the parent. */
  628. virtual TBWidget *GetEventDestination() { return m_parent; }
  629. /** Return translation the children should have. Any scrolling of child widgets
  630. should be done with this method, by returning the wanted translation.
  631. When implementing this, you must also implement ScrollTo and GetScrollInfo
  632. so focus-scroll and panning will work automatically when dragging this or
  633. any child widget. Note: You can apply the translation on one widget and
  634. implement those methods on a parent, by returning this widget from the
  635. parents GetScrollRoot(). */
  636. virtual void GetChildTranslation(int &x, int &y) const { x = y = 0; }
  637. /** If this is a widget that scroll children (see GetChildTranslation), it should
  638. scroll to the coordinates x, y.
  639. This must result in calling OnScroll if scrolling occured. */
  640. virtual void ScrollTo(int x, int y) {}
  641. /** Start the TBScroller for this widget and scroll it to the given position.
  642. Will cancel any on going smooth scroll operation. */
  643. void ScrollToSmooth(int x, int y);
  644. /** If this is a widget that scroll children (see GetChildTranslation), it will
  645. scroll by delta dx, dy relative to its current position. */
  646. void ScrollBy(int dx, int dy);
  647. /** Start the TBScroller for this widget and scroll it by the given delta.
  648. Consecutive calls will accumulate the scroll speed. */
  649. void ScrollBySmooth(int dx, int dy);
  650. /** Information about scrolling for a widget at the time of calling GetScrollInfo. */
  651. class ScrollInfo
  652. {
  653. public:
  654. ScrollInfo() : min_x(0), min_y(0), max_x(0), max_y(0), x(0), y(0) {}
  655. bool CanScrollX() const { return max_x > min_x; }
  656. bool CanScrollY() const { return max_y > min_y; }
  657. bool CanScrollLeft() const { return x > min_x; }
  658. bool CanScrollRight() const { return x < max_x; }
  659. bool CanScrollUp() const { return y > min_y; }
  660. bool CanScrollDown() const { return y < max_y; }
  661. bool CanScroll() const { return CanScrollX() || CanScrollY(); }
  662. int min_x, min_y; ///< Minimum x and y scroll position.
  663. int max_x, max_y; ///< Maximum x and y scroll position.
  664. int x, y; ///< Current x and y scroll position.
  665. };
  666. /** If this is a widget that scroll children (see GetChildTranslation),
  667. it should return the current scroll information. */
  668. virtual ScrollInfo GetScrollInfo() { return ScrollInfo(); }
  669. /** If this widget is implementing ScrollTo and GetScrollInfo but
  670. the corresponding GetChildTranslation is implemented on a child,
  671. you should return that child from this method. */
  672. virtual TBWidget *GetScrollRoot() { return this; }
  673. /** Scroll this widget and/or any parent widgets by the given delta.
  674. dx and dy will be reduced by the amount that was successfully
  675. scrolled. */
  676. void ScrollByRecursive(int &dx, int &dy);
  677. /** Make this widget visible by calling ScrollIntoView on all parent widgets */
  678. void ScrollIntoViewRecursive();
  679. /** If this is a widget that scroll children (see GetChildTranslation), it will
  680. scroll so that rect is visible. Rect is relative to this widget. */
  681. void ScrollIntoView(const TBRect &rect);
  682. /** Return the TBScroller set up for this widget, or nullptr if creation failed. */
  683. TBScroller *GetScroller();
  684. // == Setter shared for many types of widgets ============
  685. /** Set along which axis the content should be layouted. */
  686. virtual void SetAxis(AXIS axis) {}
  687. virtual AXIS GetAxis() const { return AXIS_X; }
  688. /** Set the value of this widget. Implemented by most widgets (that has a value).
  689. Note: Some widgets also provide special setters with other types (such as double). */
  690. virtual void SetValue(int value) {}
  691. virtual int GetValue() { return 0; }
  692. /** Set the value in double precision. It only makes sense to use this instead
  693. of SetValue() on widgets that store the value as double. F.ex TBScrollBar, TBSlider. */
  694. virtual void SetValueDouble(double value) { SetValue((int) value); }
  695. /** Return the value in double precision. It only makes sense to use this instead
  696. of GetValue() on widgets that store the value as double. F.ex TBScrollBar, TBSlider. */
  697. virtual double GetValueDouble() { return (double) GetValue(); }
  698. /** Set the text of this widget. Implemented by most widgets (that has text). */
  699. virtual bool SetText(const char *text) { return true; }
  700. /** Get the text of this widget. Implemented by most widgets (that has text).
  701. returns false if it failed. */
  702. virtual bool GetText(TBStr &text) { text.Clear(); return true; }
  703. /** Get the text of this widget. Implemented by most widgets (that has text). */
  704. TBStr GetText() { TBStr str; GetText(str); return str; }
  705. /** Connect this widget to a widget value.
  706. When this widget invoke EVENT_TYPE_CHANGED, it will automatically update the
  707. connected widget value, and any other widgets that may be connected to it.
  708. On connection, the value of this widget will be updated to the value of the
  709. given TBWidgetValue. */
  710. void Connect(TBWidgetValue *value) { m_connection.Connect(value, this); }
  711. /** Unconnect, if this widget is connected to a TBWidgetValue. */
  712. void Unconnect() { m_connection.Unconnect(); }
  713. /** Get the rectangle inside any padding, relative to this widget. This is the
  714. rectangle in which the content should be rendered.
  715. This may be overridden to f.ex deduct space allocated by visible scrollbars
  716. managed by this widget. Anything that removes space from the content area. */
  717. virtual TBRect GetPaddingRect();
  718. /** Calculate the preferred content size for this widget. This is the size of the actual
  719. content. Don't care about padding or other decoration. */
  720. virtual PreferredSize OnCalculatePreferredContentSize(const SizeConstraints &constraints);
  721. /** Calculate the preferred size for this widget. This is the full size of the widget,
  722. content + padding + eventual other decoration (but not skin expansion).
  723. This is the size that should be used for layouting a widget.
  724. The returned PreferredSize also contains minimal size and maximum size. */
  725. virtual PreferredSize OnCalculatePreferredSize(const SizeConstraints &constraints);
  726. /** Get the PreferredSize for this widget.
  727. This returns cached data if valid, or calls OnCalculatePreferredSize if needed. */
  728. PreferredSize GetPreferredSize(const SizeConstraints &constraints);
  729. PreferredSize GetPreferredSize() { return GetPreferredSize(SizeConstraints()); }
  730. /** Type used for InvalidateLayout */
  731. enum INVALIDATE_LAYOUT {
  732. INVALIDATE_LAYOUT_TARGET_ONLY, ///< InvalidateLayout should not be recursively called on parents.
  733. INVALIDATE_LAYOUT_RECURSIVE ///< InvalidateLayout should recursively be called on parents too.
  734. };
  735. /** Invalidate layout for this widget so it will be scheduled for relayout.
  736. Any change to the size preferences for a widget should call this to let parent layout adjust to the change.
  737. Remarks for layout widgets:
  738. - When a layout widget get this, it should mark its layout as invalid and do the layout later
  739. (in GetPreferredContentSize/GetPreferredSize are called). If a layout knows that no parents will
  740. be affected, it may stop recursion to parents to avoid unnecessary relayout.
  741. - When setting the size of a layout widget (typically from another layout widget or from a OnResize),
  742. it should be called with INVALIDATE_LAYOUT_TARGET_ONLY to avoid recursing back up to parents when
  743. already recursing down, to avoid unnecessary computation.
  744. */
  745. virtual void InvalidateLayout(INVALIDATE_LAYOUT il);
  746. /** Set layout params. Calls InvalidateLayout. */
  747. void SetLayoutParams(const LayoutParams &lp);
  748. /** Get layout params, or nullptr if not specified.
  749. Note: The layout params has already been applied to the PreferredSize returned
  750. from GetPreferredSize so you normally don't need to check these params. */
  751. const LayoutParams *GetLayoutParams() const { return m_layout_params; }
  752. // == Misc methods for invoking events. Should normally be called only on the root widget ===============
  753. /** Invoke OnProcess and OnProcessAfterChildren on this widget and its children. */
  754. void InvokeProcess();
  755. /** Invoke OnProcessStates on all child widgets, if state processing
  756. is needed (InvalidateStates() has been called) */
  757. void InvokeProcessStates(bool force_update = false);
  758. /** Invoke paint on this widget and all its children */
  759. void InvokePaint(const PaintProps &parent_paint_props);
  760. /** Invoke OnFontChanged on this widget and recursively on any children that inherit the font. */
  761. void InvokeFontChanged();
  762. /** Invoke a event on this widget.
  763. This will first check with all registered TBWidgetListener if the event should be dispatched.
  764. If the widgets OnEvent returns false (event not handled), it will continue traversing to
  765. GetEventDestination (by default the parent) until a widget handles the event.
  766. Note: When invoking event EVENT_TYPE_CHANGED, this will update the value of other widgets connected
  767. to the same group.
  768. Note: Some event types will automatically invalidate states (See InvalidateStates(), InvalidateSkinStates())
  769. Note: Remember that this widgets may be deleted after this call! So if you really must do something after
  770. this call and are not sure what the event will cause, use TBWidgetSafePointer to detect self deletion. */
  771. bool InvokeEvent(TBWidgetEvent &ev);
  772. bool InvokePointerDown(int x, int y, int click_count, MODIFIER_KEYS modifierkeys, bool touch, int touchId = 0);
  773. bool InvokePointerUp(int x, int y, MODIFIER_KEYS modifierkeys, bool touch, int touchId = 0);
  774. void InvokePointerMove(int x, int y, MODIFIER_KEYS modifierkeys, bool touch, int touchId = 0);
  775. void InvokePointerCancel();
  776. /** Invoke touch events with ref_id set as the given id.
  777. Note: For id 0, it will invoke EVENT_TYPE_POINTER_DOWN (with touch flag set to true), and EVENT_TYPE_TOUCH_DOWN
  778. for other id > 0. This results in normal interaction for first finger, and optional handling of other
  779. simultaneous interaction. GetTouchInfo(id) can be used to get additional interaction info. */
  780. bool InvokeTouchDown(int x, int y, uint32 id, int click_count, MODIFIER_KEYS modifierkeys);
  781. bool InvokeTouchUp(int x, int y, uint32 id, MODIFIER_KEYS modifierkeys);
  782. void InvokeTouchMove(int x, int y, uint32 id, MODIFIER_KEYS modifierkeys);
  783. void InvokeTouchCancel(uint32 id);
  784. void InvokeWheel(int x, int y, int delta_x, int delta_y, MODIFIER_KEYS modifierkeys);
  785. void InvokeRightPointerDown(int x, int y, int click_count, MODIFIER_KEYS modifierkeys);
  786. void InvokeRightPointerUp(int x, int y, MODIFIER_KEYS modifierkeys);
  787. /** Invoke the EVENT_TYPE_KEY_DOWN and EVENT_TYPE_KEY_UP events on the currently focused widget.
  788. This will also do some generic key handling, such as cycling focus on tab etc. */
  789. bool InvokeKey(int key, SPECIAL_KEY special_key, MODIFIER_KEYS modifierkeys, bool down);
  790. /** A widget that receive a EVENT_TYPE_POINTER_DOWN event, will stay "captured" until EVENT_TYPE_POINTER_UP
  791. is received. While captured, all EVENT_TYPE_POINTER_MOVE are sent to it. This method can force release the capture,
  792. which may happen f.ex if the TBWidget is removed while captured. */
  793. void ReleaseCapture();
  794. /** Make x and y (relative to this widget) relative to the upper left corner of the root widget. */
  795. void ConvertToRoot(int &x, int &y) const;
  796. /** Make x and y (relative to the upper left corner of the root widget) relative to this widget. */
  797. void ConvertFromRoot(int &x, int &y) const;
  798. /** Set the font description for this widget and any children that inherit the font.
  799. Setting a unspecified TBFontDescription (no changes made since construction) means
  800. it will be inherited from parent (the default).
  801. Returns true and invokes OnFontChanged on all affected widgets, if the
  802. font was successfully set.
  803. Returns false and keep the font onchanged if it no matching font exists or fails creation. */
  804. bool SetFontDescription(const TBFontDescription &font_desc);
  805. /** Get the font description as set with SetFontDescription. Use GetCalculatedFontDescription()
  806. to get the calculated font description (Inherit from parent widget etc.) */
  807. TBFontDescription GetFontDescription() const { return m_font_desc; }
  808. /** Calculate the font description for this widget. If this widget have unspecified font
  809. description, it will be inheritted from parent. If no parent specify any font,
  810. the default font description will be returned. */
  811. TBFontDescription GetCalculatedFontDescription() const;
  812. /** Get the TBFontFace for this widget from the current font description (calculated
  813. by GetCalculatedFontDescription) */
  814. TBFontFace *GetFont() const;
  815. void SetCapturing(bool needCapturing) { needCapturing_ = needCapturing; }
  816. bool GetCapturing() { return needCapturing_; }
  817. void SetCaptured(bool captured) { captured_ = captured; }
  818. bool IsCaptured() { return captured_; }
  819. void SetTouchId(unsigned touchId) { touchId_ = touchId; }
  820. unsigned GetTouchId() { return touchId_; }
  821. TBWidget *GetWidgetByTouchId(unsigned touchId);
  822. bool GetShortened() { return shortened_; }
  823. void SetShortened(bool shortened) { shortened_ = shortened; }
  824. TBStr GetTooltip() { return tooltip_; }
  825. bool SetTooltip(const char *tooltip) { return tooltip_.Set(tooltip); }
  826. private:
  827. friend class TBWidgetListener; ///< It does iteration of m_listeners for us.
  828. TBWidget *m_parent; ///< The parent of this widget
  829. TBRect m_rect; ///< The rectangle of this widget, relative to the parent. See SetRect.
  830. TBID m_id; ///< ID for GetWidgetByID and others.
  831. TBID m_group_id; ///< ID for button groups (such as TBRadioButton)
  832. TBID m_skin_bg; ///< ID for the background skin (0 for no skin).
  833. TBID m_skin_bg_expected; ///< ID for the background skin after strong override,
  834. ///< used to indirect skin changes because of condition changes.
  835. TBLinkListOf<TBWidget> m_children;///< List of child widgets
  836. TBWidgetValueConnection m_connection; ///< TBWidget value connection
  837. TBLinkListOf<TBWidgetListener> m_listeners; ///< List of listeners
  838. float m_opacity; ///< Opacity 0-1. See SetOpacity.
  839. float m_disabledOpacity; ///< Opacity 0-1. See SetDisabledOpacity.
  840. WIDGET_STATE m_state; ///< The widget state (excluding any auto states)
  841. WIDGET_GRAVITY m_gravity; ///< The layout gravity setting.
  842. TBFontDescription m_font_desc; ///< The font description.
  843. PreferredSize m_cached_ps; ///< Cached preferred size.
  844. SizeConstraints m_cached_sc; ///< Cached size constraints.
  845. LayoutParams *m_layout_params; ///< Layout params, or nullptr.
  846. TBScroller *m_scroller;
  847. TBLongClickTimer *m_long_click_timer;
  848. TBWidgetDelegate* m_delegate;
  849. bool needCapturing_; //if ours widget need capturing
  850. bool captured_; //if ours widget is currently captured
  851. unsigned touchId_;
  852. bool shortened_;
  853. TBStr tooltip_;
  854. union {
  855. struct {
  856. uint16 is_group_root : 1;
  857. uint16 is_focusable : 1;
  858. uint16 click_by_key : 1;
  859. uint16 has_key_pressed_state : 1;
  860. uint16 ignore_input : 1;
  861. uint16 is_dying : 1;
  862. uint16 is_cached_ps_valid : 1;
  863. uint16 no_automatic_hover_state : 1;
  864. uint16 is_panning : 1;
  865. uint16 want_long_click : 1;
  866. uint16 visibility : 2;
  867. uint16 inflate_child_z : 1; // Should have enough bits to hold WIDGET_Z values.
  868. } m_packed;
  869. uint16 m_packed_init;
  870. };
  871. public:
  872. /** This value is free to use for anything. It's not used by TBWidget itself. Initially TYPE_NULL. */
  873. TBValue data;
  874. // Debugging
  875. #ifdef TB_RUNTIME_DEBUG_INFO
  876. double last_measure_time;
  877. double last_layout_time;
  878. #endif // TB_RUNTIME_DEBUG_INFO
  879. // TBWidget related globals
  880. static TBWidget *hovered_widget; ///< The currently hovered widget, or nullptr.
  881. static TBWidget *captured_widget; ///< The currently captured widget, or nullptr.
  882. static TBWidget *focused_widget; ///< The currently focused widget, or nullptr.
  883. static int pointer_down_widget_x; ///< Pointer x position on down event, relative to the captured widget.
  884. static int pointer_down_widget_y; ///< Pointer y position on down event, relative to the captured widget.
  885. static int pointer_move_widget_x; ///< Pointer x position on last pointer event, relative to the captured widget (if any) or hovered widget.
  886. static int pointer_move_widget_y; ///< Pointer y position on last pointer event, relative to the captured widget (if any) or hovered widget.
  887. static bool cancel_click; ///< true if the pointer up event should not generate a click event.
  888. static bool update_widget_states; ///< true if something has called InvalidateStates() and it still hasn't been updated.
  889. static bool update_skin_states; ///< true if something has called InvalidateStates() and skin still hasn't been updated.
  890. static bool show_focus_state; ///< true if the focused state should be painted automatically.
  891. struct TOUCH_INFO {
  892. TBWidget *hovered_widget; ///< The currently hovered widget, or nullptr.
  893. TBWidget *captured_widget; ///< The currently captured widget, or nullptr.
  894. int down_widget_x; ///< Touch x position on down event, relative to the captured widget.
  895. int down_widget_y; ///< Touch y position on down event, relative to the captured widget.
  896. int move_widget_x; ///< Touch x position on last touch event, relative to the captured widget.
  897. int move_widget_y; ///< Touch y position on last touch event, relative to the captured widget.
  898. };
  899. /** Return TOUCH_INFO for the given id, or nullptr if no touch is active for that id. */
  900. static TOUCH_INFO *GetTouchInfo(uint32 id);
  901. private:
  902. /** Return this widget or the nearest parent that is scrollable
  903. in the given axis, or nullptr if there is none. */
  904. TBWidget *FindScrollableWidget(bool scroll_x, bool scroll_y);
  905. TBScroller *FindStartedScroller();
  906. TBScroller *GetReadyScroller(bool scroll_x, bool scroll_y);
  907. TBWidget *GetWidgetByIDInternal(const TBID &id, const TB_TYPE_ID type_id = nullptr);
  908. void InvokeSkinUpdatesInternal(bool force_update);
  909. void InvokeProcessInternal();
  910. static void SetHoveredWidget(TBWidget *widget, bool touch);
  911. static void SetCapturedWidget(TBWidget *widget);
  912. void HandlePanningOnMove(int x, int y);
  913. void StartLongClickTimer(bool touch);
  914. void StopLongClickTimer();
  915. friend class TBLongClickTimer;
  916. void MaybeInvokeLongClickOrContextMenu(bool touch);
  917. /** Returns the opacity for this widget multiplied with its skin opacity and state opacity. */
  918. float CalculateOpacityInternal(WIDGET_STATE state, TBSkinElement *skin_element) const;
  919. };
  920. }; // namespace tb
  921. #endif // TB_WIDGETS_H