tab_container.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. /*************************************************************************/
  2. /* tab_container.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "tab_container.h"
  31. #include "message_queue.h"
  32. int TabContainer::_get_top_margin() const {
  33. Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
  34. Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
  35. Ref<Font> font = get_font("font");
  36. int h = MAX(tab_bg->get_minimum_size().height, tab_fg->get_minimum_size().height);
  37. int ch = font->get_height();
  38. for (int i = 0; i < get_child_count(); i++) {
  39. Control *c = get_child(i)->cast_to<Control>();
  40. if (!c)
  41. continue;
  42. if (c->is_set_as_toplevel())
  43. continue;
  44. if (!c->has_meta("_tab_icon"))
  45. continue;
  46. Ref<Texture> tex = c->get_meta("_tab_icon");
  47. if (!tex.is_valid())
  48. continue;
  49. ch = MAX(ch, tex->get_size().height);
  50. }
  51. h += ch;
  52. return h;
  53. }
  54. void TabContainer::_input_event(const InputEvent &p_event) {
  55. if (p_event.type == InputEvent::MOUSE_BUTTON &&
  56. p_event.mouse_button.pressed &&
  57. p_event.mouse_button.button_index == BUTTON_LEFT) {
  58. // clicks
  59. Point2 pos(p_event.mouse_button.x, p_event.mouse_button.y);
  60. int top_margin = _get_top_margin();
  61. if (pos.y > top_margin)
  62. return; // no click (too far down)
  63. if (pos.x < tabs_ofs_cache)
  64. return; // no click (too far left)
  65. Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
  66. Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
  67. Ref<Font> font = get_font("font");
  68. Ref<Texture> incr = get_icon("increment");
  69. Ref<Texture> decr = get_icon("decrement");
  70. Ref<Texture> menu = get_icon("menu");
  71. Ref<Texture> menu_hl = get_icon("menu_hl");
  72. if (popup && pos.x > get_size().width - menu->get_width()) {
  73. emit_signal("pre_popup_pressed");
  74. Vector2 pp_pos = get_global_pos();
  75. pp_pos.x += get_size().width;
  76. pp_pos.x -= popup->get_size().width;
  77. pp_pos.y += menu->get_height();
  78. popup->set_global_pos(pp_pos);
  79. popup->popup();
  80. return;
  81. }
  82. pos.x -= tabs_ofs_cache;
  83. int idx = 0;
  84. int found = -1;
  85. bool rightroom = false;
  86. for (int i = 0; i < get_child_count(); i++) {
  87. Control *c = get_child(i)->cast_to<Control>();
  88. if (!c)
  89. continue;
  90. if (c->is_set_as_toplevel())
  91. continue;
  92. if (idx < tab_display_ofs) {
  93. idx++;
  94. continue;
  95. }
  96. if (idx > last_tab_cache) {
  97. rightroom = true;
  98. break;
  99. }
  100. String s = c->has_meta("_tab_name") ? String(XL_MESSAGE(String(c->get_meta("_tab_name")))) : String(c->get_name());
  101. int tab_width = font->get_string_size(s).width;
  102. if (c->has_meta("_tab_icon")) {
  103. Ref<Texture> icon = c->get_meta("_tab_icon");
  104. if (icon.is_valid()) {
  105. tab_width += icon->get_width();
  106. if (s != "")
  107. tab_width += get_constant("hseparation");
  108. }
  109. }
  110. if (idx == current) {
  111. tab_width += tab_fg->get_minimum_size().width;
  112. } else {
  113. tab_width += tab_bg->get_minimum_size().width;
  114. }
  115. if (pos.x < tab_width) {
  116. found = idx;
  117. break;
  118. }
  119. pos.x -= tab_width;
  120. idx++;
  121. }
  122. if (buttons_visible_cache) {
  123. if (p_event.mouse_button.x > get_size().width - incr->get_width()) {
  124. if (rightroom) {
  125. tab_display_ofs += 1;
  126. update();
  127. }
  128. } else if (p_event.mouse_button.x > get_size().width - incr->get_width() - decr->get_width()) {
  129. if (tab_display_ofs > 0) {
  130. tab_display_ofs -= 1;
  131. update();
  132. }
  133. }
  134. }
  135. if (found != -1) {
  136. set_current_tab(found);
  137. }
  138. }
  139. }
  140. void TabContainer::_notification(int p_what) {
  141. switch (p_what) {
  142. case NOTIFICATION_DRAW: {
  143. RID ci = get_canvas_item();
  144. Ref<StyleBox> panel = get_stylebox("panel");
  145. Size2 size = get_size();
  146. if (!tabs_visible) {
  147. panel->draw(ci, Rect2(0, 0, size.width, size.height));
  148. return;
  149. }
  150. Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
  151. Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
  152. Ref<Texture> incr = get_icon("increment");
  153. Ref<Texture> decr = get_icon("decrement");
  154. Ref<Texture> menu = get_icon("menu");
  155. Ref<Texture> menu_hl = get_icon("menu_hl");
  156. Ref<Font> font = get_font("font");
  157. Color color_fg = get_color("font_color_fg");
  158. Color color_bg = get_color("font_color_bg");
  159. int side_margin = get_constant("side_margin");
  160. int top_margin = _get_top_margin();
  161. Size2 top_size = Size2(size.width, top_margin);
  162. int w = 0;
  163. int idx = 0;
  164. Vector<int> offsets;
  165. Vector<Control *> controls;
  166. int from = 0;
  167. int limit = get_size().width;
  168. if (popup) {
  169. top_size.width -= menu->get_width();
  170. limit -= menu->get_width();
  171. }
  172. bool notdone = false;
  173. last_tab_cache = -1;
  174. for (int i = 0; i < get_child_count(); i++) {
  175. Control *c = get_child(i)->cast_to<Control>();
  176. if (!c)
  177. continue;
  178. if (c->is_set_as_toplevel())
  179. continue;
  180. if (idx < tab_display_ofs) {
  181. idx++;
  182. from = idx;
  183. continue;
  184. }
  185. if (w >= get_size().width) {
  186. buttons_visible_cache = true;
  187. notdone = true;
  188. break;
  189. }
  190. offsets.push_back(w);
  191. controls.push_back(c);
  192. String s = c->has_meta("_tab_name") ? String(XL_MESSAGE(String(c->get_meta("_tab_name")))) : String(c->get_name());
  193. w += font->get_string_size(s).width;
  194. if (c->has_meta("_tab_icon")) {
  195. Ref<Texture> icon = c->get_meta("_tab_icon");
  196. if (icon.is_valid()) {
  197. w += icon->get_width();
  198. if (s != "")
  199. w += get_constant("hseparation");
  200. }
  201. }
  202. if (idx == current) {
  203. w += tab_fg->get_minimum_size().width;
  204. } else {
  205. w += tab_bg->get_minimum_size().width;
  206. }
  207. if (idx < tab_display_ofs) {
  208. }
  209. last_tab_cache = idx;
  210. idx++;
  211. }
  212. int ofs;
  213. switch (align) {
  214. case ALIGN_LEFT: ofs = side_margin; break;
  215. case ALIGN_CENTER: ofs = (int(limit) - w) / 2; break;
  216. case ALIGN_RIGHT: ofs = int(limit) - w - side_margin; break;
  217. };
  218. tab_display_ofs = 0;
  219. tabs_ofs_cache = ofs;
  220. idx = 0;
  221. for (int i = 0; i < controls.size(); i++) {
  222. idx = i + from;
  223. if (current >= from && current < from + controls.size() - 1) {
  224. //current is visible! draw it last.
  225. if (i == controls.size() - 1) {
  226. idx = current;
  227. } else if (idx >= current) {
  228. idx += 1;
  229. }
  230. }
  231. Control *c = controls[idx - from];
  232. String s = c->has_meta("_tab_name") ? String(c->get_meta("_tab_name")) : String(c->get_name());
  233. int w = font->get_string_size(s).width;
  234. Ref<Texture> icon;
  235. if (c->has_meta("_tab_icon")) {
  236. icon = c->get_meta("_tab_icon");
  237. if (icon.is_valid()) {
  238. w += icon->get_width();
  239. if (s != "")
  240. w += get_constant("hseparation");
  241. }
  242. }
  243. Ref<StyleBox> sb;
  244. Color col;
  245. if (idx == current) {
  246. sb = tab_fg;
  247. col = color_fg;
  248. } else {
  249. sb = tab_bg;
  250. col = color_bg;
  251. }
  252. int lofs = ofs + offsets[idx - from];
  253. Size2i sb_ms = sb->get_minimum_size();
  254. Rect2 sb_rect = Rect2(lofs, 0, w + sb_ms.width, top_margin);
  255. sb->draw(ci, sb_rect);
  256. Point2i lpos = sb_rect.pos;
  257. lpos.x += sb->get_margin(MARGIN_LEFT);
  258. if (icon.is_valid()) {
  259. icon->draw(ci, Point2i(lpos.x, sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - icon->get_height()) / 2));
  260. if (s != "")
  261. lpos.x += icon->get_width() + get_constant("hseparation");
  262. }
  263. font->draw(ci, Point2i(lpos.x, sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - font->get_height()) / 2 + font->get_ascent()), s, col);
  264. idx++;
  265. }
  266. if (buttons_visible_cache) {
  267. int vofs = (top_margin - incr->get_height()) / 2;
  268. decr->draw(ci, Point2(limit, vofs), Color(1, 1, 1, tab_display_ofs == 0 ? 0.5 : 1.0));
  269. incr->draw(ci, Point2(limit + incr->get_width(), vofs), Color(1, 1, 1, notdone ? 1.0 : 0.5));
  270. }
  271. if (popup) {
  272. int from = get_size().width - menu->get_width();
  273. if (mouse_x_cache > from)
  274. menu_hl->draw(get_canvas_item(), Size2(from, 0));
  275. else
  276. menu->draw(get_canvas_item(), Size2(from, 0));
  277. }
  278. panel->draw(ci, Rect2(0, top_size.height, size.width, size.height - top_size.height));
  279. } break;
  280. case NOTIFICATION_THEME_CHANGED: {
  281. if (get_tab_count() > 0) {
  282. call_deferred("set_current_tab", get_current_tab()); //wait until all changed theme
  283. }
  284. } break;
  285. }
  286. }
  287. void TabContainer::_child_renamed_callback() {
  288. update();
  289. }
  290. void TabContainer::add_child_notify(Node *p_child) {
  291. Control *c = p_child->cast_to<Control>();
  292. if (!c)
  293. return;
  294. if (c->is_set_as_toplevel())
  295. return;
  296. bool first = false;
  297. if (get_tab_count() != 1)
  298. c->hide();
  299. else {
  300. c->show();
  301. //call_deferred("set_current_tab",0);
  302. first = true;
  303. current = 0;
  304. previous = 0;
  305. }
  306. c->set_area_as_parent_rect();
  307. if (tabs_visible)
  308. c->set_margin(MARGIN_TOP, _get_top_margin());
  309. Ref<StyleBox> sb = get_stylebox("panel");
  310. for (int i = 0; i < 4; i++)
  311. c->set_margin(Margin(i), c->get_margin(Margin(i)) + sb->get_margin(Margin(i)));
  312. update();
  313. p_child->connect("renamed", this, "_child_renamed_callback");
  314. if (first)
  315. emit_signal("tab_changed", current);
  316. }
  317. int TabContainer::get_tab_count() const {
  318. int count = 0;
  319. for (int i = 0; i < get_child_count(); i++) {
  320. Control *c = get_child(i)->cast_to<Control>();
  321. if (!c)
  322. continue;
  323. count++;
  324. }
  325. return count;
  326. }
  327. void TabContainer::set_current_tab(int p_current) {
  328. ERR_FAIL_INDEX(p_current, get_tab_count());
  329. int pending_previous = current;
  330. current = p_current;
  331. int idx = 0;
  332. Ref<StyleBox> sb = get_stylebox("panel");
  333. for (int i = 0; i < get_child_count(); i++) {
  334. Control *c = get_child(i)->cast_to<Control>();
  335. if (!c)
  336. continue;
  337. if (c->is_set_as_toplevel())
  338. continue;
  339. if (idx == current) {
  340. c->show();
  341. c->set_area_as_parent_rect();
  342. if (tabs_visible)
  343. c->set_margin(MARGIN_TOP, _get_top_margin());
  344. for (int i = 0; i < 4; i++)
  345. c->set_margin(Margin(i), c->get_margin(Margin(i)) + sb->get_margin(Margin(i)));
  346. } else
  347. c->hide();
  348. idx++;
  349. }
  350. _change_notify("current_tab");
  351. if (pending_previous != current)
  352. previous = pending_previous;
  353. emit_signal("tab_selected", current);
  354. emit_signal("tab_changed", current);
  355. update();
  356. }
  357. int TabContainer::get_current_tab() const {
  358. return current;
  359. }
  360. int TabContainer::get_previous_tab() const {
  361. return previous;
  362. }
  363. Control *TabContainer::get_tab_control(int p_idx) const {
  364. int idx = 0;
  365. for (int i = 0; i < get_child_count(); i++) {
  366. Control *c = get_child(i)->cast_to<Control>();
  367. if (!c)
  368. continue;
  369. if (c->is_set_as_toplevel())
  370. continue;
  371. if (idx == p_idx) {
  372. return c;
  373. }
  374. idx++;
  375. }
  376. return NULL;
  377. }
  378. Control *TabContainer::get_current_tab_control() const {
  379. int idx = 0;
  380. for (int i = 0; i < get_child_count(); i++) {
  381. Control *c = get_child(i)->cast_to<Control>();
  382. if (!c)
  383. continue;
  384. if (c->is_set_as_toplevel())
  385. continue;
  386. if (idx == current) {
  387. return c;
  388. }
  389. idx++;
  390. }
  391. return NULL;
  392. }
  393. void TabContainer::remove_child_notify(Node *p_child) {
  394. int tc = get_tab_count();
  395. if (current == tc - 1) {
  396. current--;
  397. if (current < 0)
  398. current = 0;
  399. else {
  400. call_deferred("set_current_tab", current);
  401. }
  402. }
  403. p_child->disconnect("renamed", this, "_child_renamed_callback");
  404. update();
  405. }
  406. void TabContainer::set_tab_align(TabAlign p_align) {
  407. ERR_FAIL_INDEX(p_align, 3);
  408. align = p_align;
  409. update();
  410. _change_notify("tab_align");
  411. }
  412. TabContainer::TabAlign TabContainer::get_tab_align() const {
  413. return align;
  414. }
  415. void TabContainer::set_tabs_visible(bool p_visibe) {
  416. if (p_visibe == tabs_visible)
  417. return;
  418. tabs_visible = p_visibe;
  419. for (int i = 0; i < get_child_count(); i++) {
  420. Control *c = get_child(i)->cast_to<Control>();
  421. if (!c)
  422. continue;
  423. if (p_visibe)
  424. c->set_margin(MARGIN_TOP, _get_top_margin());
  425. else
  426. c->set_margin(MARGIN_TOP, 0);
  427. }
  428. update();
  429. }
  430. bool TabContainer::are_tabs_visible() const {
  431. return tabs_visible;
  432. }
  433. Control *TabContainer::_get_tab(int p_idx) const {
  434. int idx = 0;
  435. for (int i = 0; i < get_child_count(); i++) {
  436. Control *c = get_child(i)->cast_to<Control>();
  437. if (!c)
  438. continue;
  439. if (c->is_set_as_toplevel())
  440. continue;
  441. if (idx == p_idx)
  442. return c;
  443. idx++;
  444. }
  445. return NULL;
  446. }
  447. void TabContainer::set_tab_title(int p_tab, const String &p_title) {
  448. Control *child = _get_tab(p_tab);
  449. ERR_FAIL_COND(!child);
  450. child->set_meta("_tab_name", p_title);
  451. }
  452. String TabContainer::get_tab_title(int p_tab) const {
  453. Control *child = _get_tab(p_tab);
  454. ERR_FAIL_COND_V(!child, "");
  455. if (child->has_meta("_tab_name"))
  456. return child->get_meta("_tab_name");
  457. else
  458. return child->get_name();
  459. }
  460. void TabContainer::set_tab_icon(int p_tab, const Ref<Texture> &p_icon) {
  461. Control *child = _get_tab(p_tab);
  462. ERR_FAIL_COND(!child);
  463. child->set_meta("_tab_icon", p_icon);
  464. }
  465. Ref<Texture> TabContainer::get_tab_icon(int p_tab) const {
  466. Control *child = _get_tab(p_tab);
  467. ERR_FAIL_COND_V(!child, Ref<Texture>());
  468. if (child->has_meta("_tab_icon"))
  469. return child->get_meta("_tab_icon");
  470. else
  471. return Ref<Texture>();
  472. }
  473. void TabContainer::get_translatable_strings(List<String> *p_strings) const {
  474. for (int i = 0; i < get_child_count(); i++) {
  475. Control *c = get_child(i)->cast_to<Control>();
  476. if (!c)
  477. continue;
  478. if (c->is_set_as_toplevel())
  479. continue;
  480. if (!c->has_meta("_tab_name"))
  481. continue;
  482. String name = c->get_meta("_tab_name");
  483. if (name != "")
  484. p_strings->push_back(name);
  485. }
  486. }
  487. Size2 TabContainer::get_minimum_size() const {
  488. Size2 ms;
  489. for (int i = 0; i < get_child_count(); i++) {
  490. Control *c = get_child(i)->cast_to<Control>();
  491. if (!c)
  492. continue;
  493. if (c->is_set_as_toplevel())
  494. continue;
  495. if (!c->is_visible())
  496. continue;
  497. Size2 cms = c->get_combined_minimum_size();
  498. ms.x = MAX(ms.x, cms.x);
  499. ms.y = MAX(ms.y, cms.y);
  500. }
  501. Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
  502. Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
  503. Ref<Font> font = get_font("font");
  504. ms.y += MAX(tab_bg->get_minimum_size().y, tab_fg->get_minimum_size().y);
  505. ms.y += font->get_height();
  506. Ref<StyleBox> sb = get_stylebox("panel");
  507. ms += sb->get_minimum_size();
  508. return ms;
  509. }
  510. void TabContainer::set_popup(Node *p_popup) {
  511. ERR_FAIL_NULL(p_popup);
  512. popup = p_popup->cast_to<Popup>();
  513. update();
  514. }
  515. Popup *TabContainer::get_popup() const {
  516. return popup;
  517. }
  518. void TabContainer::_bind_methods() {
  519. ObjectTypeDB::bind_method(_MD("_input_event"), &TabContainer::_input_event);
  520. ObjectTypeDB::bind_method(_MD("get_tab_count"), &TabContainer::get_tab_count);
  521. ObjectTypeDB::bind_method(_MD("set_current_tab", "tab_idx"), &TabContainer::set_current_tab);
  522. ObjectTypeDB::bind_method(_MD("get_current_tab"), &TabContainer::get_current_tab);
  523. ObjectTypeDB::bind_method(_MD("get_previous_tab"), &TabContainer::get_previous_tab);
  524. ObjectTypeDB::bind_method(_MD("get_current_tab_control:Control"), &TabContainer::get_current_tab_control);
  525. ObjectTypeDB::bind_method(_MD("get_tab_control:Control", "idx"), &TabContainer::get_tab_control);
  526. ObjectTypeDB::bind_method(_MD("set_tab_align", "align"), &TabContainer::set_tab_align);
  527. ObjectTypeDB::bind_method(_MD("get_tab_align"), &TabContainer::get_tab_align);
  528. ObjectTypeDB::bind_method(_MD("set_tabs_visible", "visible"), &TabContainer::set_tabs_visible);
  529. ObjectTypeDB::bind_method(_MD("are_tabs_visible"), &TabContainer::are_tabs_visible);
  530. ObjectTypeDB::bind_method(_MD("set_tab_title", "tab_idx", "title"), &TabContainer::set_tab_title);
  531. ObjectTypeDB::bind_method(_MD("get_tab_title", "tab_idx"), &TabContainer::get_tab_title);
  532. ObjectTypeDB::bind_method(_MD("set_tab_icon", "tab_idx", "icon:Texture"), &TabContainer::set_tab_icon);
  533. ObjectTypeDB::bind_method(_MD("get_tab_icon:Texture", "tab_idx"), &TabContainer::get_tab_icon);
  534. ObjectTypeDB::bind_method(_MD("set_popup", "popup:Popup"), &TabContainer::set_popup);
  535. ObjectTypeDB::bind_method(_MD("get_popup:Popup"), &TabContainer::get_popup);
  536. ObjectTypeDB::bind_method(_MD("_child_renamed_callback"), &TabContainer::_child_renamed_callback);
  537. ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
  538. ADD_SIGNAL(MethodInfo("tab_selected", PropertyInfo(Variant::INT, "tab")));
  539. ADD_SIGNAL(MethodInfo("pre_popup_pressed"));
  540. ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), _SCS("set_tab_align"), _SCS("get_tab_align"));
  541. ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), _SCS("set_current_tab"), _SCS("get_current_tab"));
  542. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_visible"), _SCS("set_tabs_visible"), _SCS("are_tabs_visible"));
  543. }
  544. TabContainer::TabContainer() {
  545. tab_display_ofs = 0;
  546. buttons_visible_cache = false;
  547. tabs_ofs_cache = 0;
  548. current = 0;
  549. previous = 0;
  550. mouse_x_cache = 0;
  551. align = ALIGN_CENTER;
  552. tabs_visible = true;
  553. popup = NULL;
  554. }