void Tabs::_ensure_no_over_offset() { if (!is_inside_tree()) return; Ref<Texture> incr = get_icon("increment"); Ref<Texture> decr = get_icon("decrement"); int limit = get_size().width - incr->get_width() - decr->get_width(); while (offset > 0) { int total_w = 0; for (int i = 0; i < tabs.size(); i++) { if (i < offset - 1) continue; total_w += get_tab_width(i); } if (total_w < limit) { offset--; update(); } else { break; } } }
void Tabs::ensure_tab_visible(int p_idx) { if (!is_inside_tree()) return; ERR_FAIL_INDEX(p_idx,tabs.size()); _ensure_no_over_offset(); if (p_idx<=offset) { offset=p_idx; update(); return; } Ref<Texture> incr = get_icon("increment"); Ref<Texture> decr = get_icon("decrement"); int limit=get_size().width-incr->get_width()-decr->get_width(); int x=0; for(int i=0;i<tabs.size();i++) { if (i<offset) continue; int sz = get_tab_width(i); tabs[i].x_cache=x; tabs[i].x_size_cache=sz; x+=sz; } while(offset<tabs.size() && ( (tabs[p_idx].x_cache + tabs[p_idx].x_size_cache) - tabs[offset].x_cache) > limit) { offset++; } update(); }
void Tabs::_notification(int p_what) { switch (p_what) { case NOTIFICATION_MOUSE_EXIT: { rb_hover = -1; cb_hover = -1; hover = -1; update(); } break; case NOTIFICATION_RESIZED: { _ensure_no_over_offset(); } break; case NOTIFICATION_DRAW: { RID ci = get_canvas_item(); Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); Ref<Font> font = get_font("font"); Color color_fg = get_color("font_color_fg"); Color color_bg = get_color("font_color_bg"); Ref<Texture> close = get_icon("close"); int h = get_size().height; int w = 0; int mw = 0; for (int i = 0; i < tabs.size(); i++) { tabs[i].ofs_cache = mw; mw += get_tab_width(i); } if (tab_align == ALIGN_CENTER) { w = (get_size().width - mw) / 2; } else if (tab_align == ALIGN_RIGHT) { w = get_size().width - mw; } if (w < 0) { w = 0; } Ref<Texture> incr = get_icon("increment"); Ref<Texture> decr = get_icon("decrement"); Ref<Texture> incr_hl = get_icon("increment_hilite"); Ref<Texture> decr_hl = get_icon("decrement_hilite"); int limit = get_size().width - incr->get_size().width - decr->get_size().width; missing_right = false; for (int i = 0; i < tabs.size(); i++) { if (i < offset) continue; tabs[i].ofs_cache = w; int lsize = get_tab_width(i); String text = tabs[i].text; int slen = font->get_string_size(text).width; if (w + lsize > limit) { max_drawn_tab = i - 1; missing_right = true; break; } else { max_drawn_tab = i; } Ref<StyleBox> sb; Color col; if (i == current) { sb = tab_fg; col = color_fg; } else { sb = tab_bg; col = color_bg; } Rect2 sb_rect = Rect2(w, 0, lsize, h); sb->draw(ci, sb_rect); w += sb->get_margin(MARGIN_LEFT); Size2i sb_ms = sb->get_minimum_size(); Ref<Texture> icon = tabs[i].icon; if (icon.is_valid()) { icon->draw(ci, Point2i(w, sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - icon->get_height()) / 2)); if (text != "") w += icon->get_width() + get_constant("hseparation"); } font->draw(ci, Point2i(w, sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - font->get_height()) / 2 + font->get_ascent()), text, col); w += slen; if (tabs[i].right_button.is_valid()) { Ref<StyleBox> style = get_stylebox("button"); Ref<Texture> rb = tabs[i].right_button; w += get_constant("hseparation"); Rect2 rb_rect; rb_rect.size = style->get_minimum_size() + rb->get_size(); rb_rect.pos.x = w; rb_rect.pos.y = sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - (rb_rect.size.y)) / 2; if (rb_hover == i) { if (rb_pressing) get_stylebox("button_pressed")->draw(ci, rb_rect); else style->draw(ci, rb_rect); } rb->draw(ci, Point2i(w + style->get_margin(MARGIN_LEFT), rb_rect.pos.y + style->get_margin(MARGIN_TOP))); w += rb->get_width(); tabs[i].rb_rect = rb_rect; } if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) { Ref<StyleBox> style = get_stylebox("button"); Ref<Texture> cb = close; w += get_constant("hseparation"); Rect2 cb_rect; cb_rect.size = style->get_minimum_size() + cb->get_size(); cb_rect.pos.x = w; cb_rect.pos.y = sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - (cb_rect.size.y)) / 2; if (cb_hover == i) { if (cb_pressing) get_stylebox("button_pressed")->draw(ci, cb_rect); else style->draw(ci, cb_rect); } cb->draw(ci, Point2i(w + style->get_margin(MARGIN_LEFT), cb_rect.pos.y + style->get_margin(MARGIN_TOP))); w += cb->get_width(); tabs[i].cb_rect = cb_rect; } w += sb->get_margin(MARGIN_RIGHT); tabs[i].size_cache = w - tabs[i].ofs_cache; } if (offset > 0 || missing_right) { int vofs = (get_size().height - incr->get_size().height) / 2; if (offset > 0) draw_texture(hilite_arrow == 0 ? decr_hl : decr, Point2(limit, vofs)); else draw_texture(decr, Point2(limit, vofs), Color(1, 1, 1, 0.5)); if (missing_right) draw_texture(hilite_arrow == 1 ? incr_hl : incr, Point2(limit + decr->get_size().width, vofs)); else draw_texture(incr, Point2(limit + decr->get_size().width, vofs), Color(1, 1, 1, 0.5)); buttons_visible = true; } else { buttons_visible = false; } } break; } }
void Tabs::_update_cache() { Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled"); Ref<StyleBox> tab_bg = get_stylebox("tab_bg"); Ref<StyleBox> tab_fg = get_stylebox("tab_fg"); Ref<Font> font = get_font("font"); Ref<Texture> incr = get_icon("increment"); Ref<Texture> decr = get_icon("decrement"); int limit = get_size().width - incr->get_width() - decr->get_width(); int w = 0; int mw = 0; int size_fixed = 0; int count_resize = 0; for (int i = 0; i < tabs.size(); i++) { tabs[i].ofs_cache = mw; tabs[i].size_cache = get_tab_width(i); tabs[i].size_text = font->get_string_size(tabs[i].text).width; mw += tabs[i].size_cache; if (tabs[i].size_cache <= min_width || i == current) { size_fixed += tabs[i].size_cache; } else { count_resize++; } } int m_width = min_width; if (count_resize > 0) { m_width = MAX((limit - size_fixed) / count_resize, min_width); } for (int i = 0; i < tabs.size(); i++) { if (i < offset) continue; Ref<StyleBox> sb; if (tabs[i].disabled) { sb = tab_disabled; } else if (i == current) { sb = tab_fg; } else { sb = tab_bg; } int lsize = tabs[i].size_cache; int slen = tabs[i].size_text; if (min_width > 0 && mw > limit && i != current) { if (lsize > m_width) { slen = m_width - (sb->get_margin(MARGIN_LEFT) + sb->get_margin(MARGIN_RIGHT)); if (tabs[i].icon.is_valid()) { slen -= tabs[i].icon->get_width(); slen -= get_constant("hseparation"); } if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) { Ref<Texture> cb = get_icon("close"); slen -= cb->get_width(); slen -= get_constant("hseparation"); } slen = MAX(slen, 1); lsize = m_width; } } tabs[i].ofs_cache = w; tabs[i].size_cache = lsize; tabs[i].size_text = slen; w += lsize; } }