mirror of
https://github.com/godotengine/godot.git
synced 2024-11-10 14:12:51 +00:00
Add a lifecycle method for manual theme item caching to Control
This commit is contained in:
parent
0c221f0284
commit
3b1aa240dc
@ -44,7 +44,6 @@ void BoxContainer::_resort() {
|
||||
|
||||
Size2i new_size = get_size();
|
||||
|
||||
int sep = get_theme_constant(SNAME("separation")); //,vertical?"VBoxContainer":"HBoxContainer");
|
||||
bool rtl = is_layout_rtl();
|
||||
|
||||
bool first = true;
|
||||
@ -90,7 +89,7 @@ void BoxContainer::_resort() {
|
||||
return;
|
||||
}
|
||||
|
||||
int stretch_max = (vertical ? new_size.height : new_size.width) - (children_count - 1) * sep;
|
||||
int stretch_max = (vertical ? new_size.height : new_size.width) - (children_count - 1) * theme_cache.separation;
|
||||
int stretch_diff = stretch_max - stretch_min;
|
||||
if (stretch_diff < 0) {
|
||||
//avoid negative stretch space
|
||||
@ -214,7 +213,7 @@ void BoxContainer::_resort() {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
ofs += sep;
|
||||
ofs += theme_cache.separation;
|
||||
}
|
||||
|
||||
int from = ofs;
|
||||
@ -248,7 +247,6 @@ Size2 BoxContainer::get_minimum_size() const {
|
||||
/* Calculate MINIMUM SIZE */
|
||||
|
||||
Size2i minimum;
|
||||
int sep = get_theme_constant(SNAME("separation")); //,vertical?"VBoxContainer":"HBoxContainer");
|
||||
|
||||
bool first = true;
|
||||
|
||||
@ -273,7 +271,7 @@ Size2 BoxContainer::get_minimum_size() const {
|
||||
minimum.width = size.width;
|
||||
}
|
||||
|
||||
minimum.height += size.height + (first ? 0 : sep);
|
||||
minimum.height += size.height + (first ? 0 : theme_cache.separation);
|
||||
|
||||
} else { /* HORIZONTAL */
|
||||
|
||||
@ -281,7 +279,7 @@ Size2 BoxContainer::get_minimum_size() const {
|
||||
minimum.height = size.height;
|
||||
}
|
||||
|
||||
minimum.width += size.width + (first ? 0 : sep);
|
||||
minimum.width += size.width + (first ? 0 : theme_cache.separation);
|
||||
}
|
||||
|
||||
first = false;
|
||||
@ -290,6 +288,12 @@ Size2 BoxContainer::get_minimum_size() const {
|
||||
return minimum;
|
||||
}
|
||||
|
||||
void BoxContainer::_update_theme_item_cache() {
|
||||
Container::_update_theme_item_cache();
|
||||
|
||||
theme_cache.separation = get_theme_constant(SNAME("separation")); //,vertical?"VBoxContainer":"HBoxContainer");
|
||||
}
|
||||
|
||||
void BoxContainer::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_SORT_CHILDREN: {
|
||||
|
@ -47,11 +47,16 @@ private:
|
||||
bool vertical = false;
|
||||
AlignmentMode alignment = ALIGNMENT_BEGIN;
|
||||
|
||||
struct ThemeCache {
|
||||
int separation = 0;
|
||||
} theme_cache;
|
||||
|
||||
void _resort();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
@ -36,7 +36,7 @@
|
||||
Size2 Button::get_minimum_size() const {
|
||||
Ref<Texture2D> _icon = icon;
|
||||
if (_icon.is_null() && has_theme_icon(SNAME("icon"))) {
|
||||
_icon = Control::get_theme_icon(SNAME("icon"));
|
||||
_icon = theme_cache.icon;
|
||||
}
|
||||
|
||||
return get_minimum_size_for_text_and_icon("", _icon);
|
||||
@ -46,6 +46,45 @@ void Button::_set_internal_margin(Side p_side, float p_value) {
|
||||
_internal_margin[p_side] = p_value;
|
||||
}
|
||||
|
||||
void Button::_update_theme_item_cache() {
|
||||
BaseButton::_update_theme_item_cache();
|
||||
|
||||
theme_cache.normal = get_theme_stylebox(SNAME("normal"));
|
||||
theme_cache.normal_mirrored = get_theme_stylebox(SNAME("normal_mirrored"));
|
||||
theme_cache.pressed = get_theme_stylebox(SNAME("pressed"));
|
||||
theme_cache.pressed_mirrored = get_theme_stylebox(SNAME("pressed_mirrored"));
|
||||
theme_cache.hover = get_theme_stylebox(SNAME("hover"));
|
||||
theme_cache.hover_mirrored = get_theme_stylebox(SNAME("hover_mirrored"));
|
||||
theme_cache.hover_pressed = get_theme_stylebox(SNAME("hover_pressed"));
|
||||
theme_cache.hover_pressed_mirrored = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
|
||||
theme_cache.disabled = get_theme_stylebox(SNAME("disabled"));
|
||||
theme_cache.disabled_mirrored = get_theme_stylebox(SNAME("disabled_mirrored"));
|
||||
theme_cache.focus = get_theme_stylebox(SNAME("focus"));
|
||||
|
||||
theme_cache.font_color = get_theme_color(SNAME("font_color"));
|
||||
theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
|
||||
theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
|
||||
theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
|
||||
theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
|
||||
theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
|
||||
|
||||
theme_cache.font = get_theme_font(SNAME("font"));
|
||||
theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
|
||||
theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
|
||||
theme_cache.icon_normal_color = get_theme_color(SNAME("icon_normal_color"));
|
||||
theme_cache.icon_focus_color = get_theme_color(SNAME("icon_focus_color"));
|
||||
theme_cache.icon_pressed_color = get_theme_color(SNAME("icon_pressed_color"));
|
||||
theme_cache.icon_hover_color = get_theme_color(SNAME("icon_hover_color"));
|
||||
theme_cache.icon_hover_pressed_color = get_theme_color(SNAME("icon_hover_pressed_color"));
|
||||
theme_cache.icon_disabled_color = get_theme_color(SNAME("icon_disabled_color"));
|
||||
|
||||
theme_cache.icon = get_theme_icon(SNAME("icon"));
|
||||
|
||||
theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
|
||||
}
|
||||
|
||||
void Button::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
|
||||
@ -73,15 +112,15 @@ void Button::_notification(int p_what) {
|
||||
Color color;
|
||||
Color color_icon(1, 1, 1, 1);
|
||||
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
Ref<StyleBox> style = theme_cache.normal;
|
||||
bool rtl = is_layout_rtl();
|
||||
|
||||
switch (get_draw_mode()) {
|
||||
case DRAW_NORMAL: {
|
||||
if (rtl && has_theme_stylebox(SNAME("normal_mirrored"))) {
|
||||
style = get_theme_stylebox(SNAME("normal_mirrored"));
|
||||
style = theme_cache.normal_mirrored;
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("normal"));
|
||||
style = theme_cache.normal;
|
||||
}
|
||||
|
||||
if (!flat) {
|
||||
@ -90,14 +129,14 @@ void Button::_notification(int p_what) {
|
||||
|
||||
// Focus colors only take precedence over normal state.
|
||||
if (has_focus()) {
|
||||
color = get_theme_color(SNAME("font_focus_color"));
|
||||
color = theme_cache.font_focus_color;
|
||||
if (has_theme_color(SNAME("icon_focus_color"))) {
|
||||
color_icon = get_theme_color(SNAME("icon_focus_color"));
|
||||
color_icon = theme_cache.icon_focus_color;
|
||||
}
|
||||
} else {
|
||||
color = get_theme_color(SNAME("font_color"));
|
||||
color = theme_cache.font_color;
|
||||
if (has_theme_color(SNAME("icon_normal_color"))) {
|
||||
color_icon = get_theme_color(SNAME("icon_normal_color"));
|
||||
color_icon = theme_cache.icon_normal_color;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@ -105,19 +144,19 @@ void Button::_notification(int p_what) {
|
||||
// Edge case for CheckButton and CheckBox.
|
||||
if (has_theme_stylebox("hover_pressed")) {
|
||||
if (rtl && has_theme_stylebox(SNAME("hover_pressed_mirrored"))) {
|
||||
style = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
|
||||
style = theme_cache.hover_pressed_mirrored;
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("hover_pressed"));
|
||||
style = theme_cache.hover_pressed;
|
||||
}
|
||||
|
||||
if (!flat) {
|
||||
style->draw(ci, Rect2(Point2(0, 0), size));
|
||||
}
|
||||
if (has_theme_color(SNAME("font_hover_pressed_color"))) {
|
||||
color = get_theme_color(SNAME("font_hover_pressed_color"));
|
||||
color = theme_cache.font_hover_pressed_color;
|
||||
}
|
||||
if (has_theme_color(SNAME("icon_hover_pressed_color"))) {
|
||||
color_icon = get_theme_color(SNAME("icon_hover_pressed_color"));
|
||||
color_icon = theme_cache.icon_hover_pressed_color;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -126,53 +165,53 @@ void Button::_notification(int p_what) {
|
||||
}
|
||||
case DRAW_PRESSED: {
|
||||
if (rtl && has_theme_stylebox(SNAME("pressed_mirrored"))) {
|
||||
style = get_theme_stylebox(SNAME("pressed_mirrored"));
|
||||
style = theme_cache.pressed_mirrored;
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("pressed"));
|
||||
style = theme_cache.pressed;
|
||||
}
|
||||
|
||||
if (!flat) {
|
||||
style->draw(ci, Rect2(Point2(0, 0), size));
|
||||
}
|
||||
if (has_theme_color(SNAME("font_pressed_color"))) {
|
||||
color = get_theme_color(SNAME("font_pressed_color"));
|
||||
color = theme_cache.font_pressed_color;
|
||||
} else {
|
||||
color = get_theme_color(SNAME("font_color"));
|
||||
color = theme_cache.font_color;
|
||||
}
|
||||
if (has_theme_color(SNAME("icon_pressed_color"))) {
|
||||
color_icon = get_theme_color(SNAME("icon_pressed_color"));
|
||||
color_icon = theme_cache.icon_pressed_color;
|
||||
}
|
||||
|
||||
} break;
|
||||
case DRAW_HOVER: {
|
||||
if (rtl && has_theme_stylebox(SNAME("hover_mirrored"))) {
|
||||
style = get_theme_stylebox(SNAME("hover_mirrored"));
|
||||
style = theme_cache.hover_mirrored;
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("hover"));
|
||||
style = theme_cache.hover;
|
||||
}
|
||||
|
||||
if (!flat) {
|
||||
style->draw(ci, Rect2(Point2(0, 0), size));
|
||||
}
|
||||
color = get_theme_color(SNAME("font_hover_color"));
|
||||
color = theme_cache.font_hover_color;
|
||||
if (has_theme_color(SNAME("icon_hover_color"))) {
|
||||
color_icon = get_theme_color(SNAME("icon_hover_color"));
|
||||
color_icon = theme_cache.icon_hover_color;
|
||||
}
|
||||
|
||||
} break;
|
||||
case DRAW_DISABLED: {
|
||||
if (rtl && has_theme_stylebox(SNAME("disabled_mirrored"))) {
|
||||
style = get_theme_stylebox(SNAME("disabled_mirrored"));
|
||||
style = theme_cache.disabled_mirrored;
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("disabled"));
|
||||
style = theme_cache.disabled;
|
||||
}
|
||||
|
||||
if (!flat) {
|
||||
style->draw(ci, Rect2(Point2(0, 0), size));
|
||||
}
|
||||
color = get_theme_color(SNAME("font_disabled_color"));
|
||||
color = theme_cache.font_disabled_color;
|
||||
if (has_theme_color(SNAME("icon_disabled_color"))) {
|
||||
color_icon = get_theme_color(SNAME("icon_disabled_color"));
|
||||
color_icon = theme_cache.icon_disabled_color;
|
||||
} else {
|
||||
color_icon.a = 0.4;
|
||||
}
|
||||
@ -181,13 +220,13 @@ void Button::_notification(int p_what) {
|
||||
}
|
||||
|
||||
if (has_focus()) {
|
||||
Ref<StyleBox> style2 = get_theme_stylebox(SNAME("focus"));
|
||||
Ref<StyleBox> style2 = theme_cache.focus;
|
||||
style2->draw(ci, Rect2(Point2(), size));
|
||||
}
|
||||
|
||||
Ref<Texture2D> _icon;
|
||||
if (icon.is_null() && has_theme_icon(SNAME("icon"))) {
|
||||
_icon = Control::get_theme_icon(SNAME("icon"));
|
||||
_icon = theme_cache.icon;
|
||||
} else {
|
||||
_icon = icon;
|
||||
}
|
||||
@ -217,21 +256,21 @@ void Button::_notification(int p_what) {
|
||||
if (icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_LEFT) {
|
||||
style_offset.x = style->get_margin(SIDE_LEFT);
|
||||
if (_internal_margin[SIDE_LEFT] > 0) {
|
||||
icon_ofs_region = _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("h_separation"));
|
||||
icon_ofs_region = _internal_margin[SIDE_LEFT] + theme_cache.h_separation;
|
||||
}
|
||||
} else if (icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER) {
|
||||
style_offset.x = 0.0;
|
||||
} else if (icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_RIGHT) {
|
||||
style_offset.x = -style->get_margin(SIDE_RIGHT);
|
||||
if (_internal_margin[SIDE_RIGHT] > 0) {
|
||||
icon_ofs_region = -_internal_margin[SIDE_RIGHT] - get_theme_constant(SNAME("h_separation"));
|
||||
icon_ofs_region = -_internal_margin[SIDE_RIGHT] - theme_cache.h_separation;
|
||||
}
|
||||
}
|
||||
style_offset.y = style->get_margin(SIDE_TOP);
|
||||
|
||||
if (expand_icon) {
|
||||
Size2 _size = get_size() - style->get_offset() * 2;
|
||||
int icon_text_separation = text.is_empty() ? 0 : get_theme_constant(SNAME("h_separation"));
|
||||
int icon_text_separation = text.is_empty() ? 0 : theme_cache.h_separation;
|
||||
_size.width -= icon_text_separation + icon_ofs_region;
|
||||
if (!clip_text && icon_align_rtl_checked != HORIZONTAL_ALIGNMENT_CENTER) {
|
||||
_size.width -= text_buf->get_size().width;
|
||||
@ -261,7 +300,7 @@ void Button::_notification(int p_what) {
|
||||
}
|
||||
}
|
||||
|
||||
Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_theme_constant(SNAME("h_separation")), 0) : Point2();
|
||||
Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + theme_cache.h_separation, 0) : Point2();
|
||||
if (align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER && icon_align_rtl_checked == HORIZONTAL_ALIGNMENT_CENTER) {
|
||||
icon_ofs.x = 0.0;
|
||||
}
|
||||
@ -271,10 +310,10 @@ void Button::_notification(int p_what) {
|
||||
int text_width = MAX(1, (clip_text || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x);
|
||||
|
||||
if (_internal_margin[SIDE_LEFT] > 0) {
|
||||
text_clip -= _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("h_separation"));
|
||||
text_clip -= _internal_margin[SIDE_LEFT] + theme_cache.h_separation;
|
||||
}
|
||||
if (_internal_margin[SIDE_RIGHT] > 0) {
|
||||
text_clip -= _internal_margin[SIDE_RIGHT] + get_theme_constant(SNAME("h_separation"));
|
||||
text_clip -= _internal_margin[SIDE_RIGHT] + theme_cache.h_separation;
|
||||
}
|
||||
|
||||
Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - text_buf->get_size() - Point2(_internal_margin[SIDE_RIGHT] - _internal_margin[SIDE_LEFT], 0)) / 2.0;
|
||||
@ -288,7 +327,7 @@ void Button::_notification(int p_what) {
|
||||
icon_ofs.x = 0.0;
|
||||
}
|
||||
if (_internal_margin[SIDE_LEFT] > 0) {
|
||||
text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x + _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("h_separation"));
|
||||
text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x + _internal_margin[SIDE_LEFT] + theme_cache.h_separation;
|
||||
} else {
|
||||
text_ofs.x = style->get_margin(SIDE_LEFT) + icon_ofs.x;
|
||||
}
|
||||
@ -305,7 +344,7 @@ void Button::_notification(int p_what) {
|
||||
} break;
|
||||
case HORIZONTAL_ALIGNMENT_RIGHT: {
|
||||
if (_internal_margin[SIDE_RIGHT] > 0) {
|
||||
text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width - _internal_margin[SIDE_RIGHT] - get_theme_constant(SNAME("h_separation"));
|
||||
text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width - _internal_margin[SIDE_RIGHT] - theme_cache.h_separation;
|
||||
} else {
|
||||
text_ofs.x = size.x - style->get_margin(SIDE_RIGHT) - text_width;
|
||||
}
|
||||
@ -316,8 +355,8 @@ void Button::_notification(int p_what) {
|
||||
} break;
|
||||
}
|
||||
|
||||
Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
int outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
Color font_outline_color = theme_cache.font_outline_color;
|
||||
int outline_size = theme_cache.outline_size;
|
||||
if (outline_size > 0 && font_outline_color.a > 0) {
|
||||
text_buf->draw_outline(ci, text_ofs, outline_size, font_outline_color);
|
||||
}
|
||||
@ -346,7 +385,7 @@ Size2 Button::get_minimum_size_for_text_and_icon(const String &p_text, Ref<Textu
|
||||
if (icon_alignment != HORIZONTAL_ALIGNMENT_CENTER) {
|
||||
minsize.width += p_icon->get_width();
|
||||
if (!xl_text.is_empty() || !p_text.is_empty()) {
|
||||
minsize.width += MAX(0, get_theme_constant(SNAME("h_separation")));
|
||||
minsize.width += MAX(0, theme_cache.h_separation);
|
||||
}
|
||||
} else {
|
||||
minsize.width = MAX(minsize.width, p_icon->get_width());
|
||||
@ -354,12 +393,12 @@ Size2 Button::get_minimum_size_for_text_and_icon(const String &p_text, Ref<Textu
|
||||
}
|
||||
|
||||
if (!xl_text.is_empty() || !p_text.is_empty()) {
|
||||
Ref<Font> font = get_theme_font(SNAME("font"));
|
||||
float font_height = font->get_height(get_theme_font_size(SNAME("font_size")));
|
||||
Ref<Font> font = theme_cache.font;
|
||||
float font_height = font->get_height(theme_cache.font_size);
|
||||
minsize.height = MAX(font_height, minsize.height);
|
||||
}
|
||||
|
||||
return get_theme_stylebox(SNAME("normal"))->get_minimum_size() + minsize;
|
||||
return theme_cache.normal->get_minimum_size() + minsize;
|
||||
}
|
||||
|
||||
void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) {
|
||||
@ -371,10 +410,15 @@ void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) {
|
||||
p_text = xl_text;
|
||||
}
|
||||
|
||||
Ref<Font> font = get_theme_font(SNAME("font"));
|
||||
int font_size = get_theme_font_size(SNAME("font_size"));
|
||||
|
||||
p_paragraph->clear();
|
||||
|
||||
Ref<Font> font = theme_cache.font;
|
||||
int font_size = theme_cache.font_size;
|
||||
if (font.is_null() || font_size == 0) {
|
||||
// Can't shape without a valid font and a non-zero size.
|
||||
return;
|
||||
}
|
||||
|
||||
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
|
||||
p_paragraph->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
|
||||
} else {
|
||||
|
@ -54,10 +54,48 @@ private:
|
||||
HorizontalAlignment icon_alignment = HORIZONTAL_ALIGNMENT_LEFT;
|
||||
float _internal_margin[4] = {};
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> normal;
|
||||
Ref<StyleBox> normal_mirrored;
|
||||
Ref<StyleBox> pressed;
|
||||
Ref<StyleBox> pressed_mirrored;
|
||||
Ref<StyleBox> hover;
|
||||
Ref<StyleBox> hover_mirrored;
|
||||
Ref<StyleBox> hover_pressed;
|
||||
Ref<StyleBox> hover_pressed_mirrored;
|
||||
Ref<StyleBox> disabled;
|
||||
Ref<StyleBox> disabled_mirrored;
|
||||
Ref<StyleBox> focus;
|
||||
|
||||
Color font_color;
|
||||
Color font_focus_color;
|
||||
Color font_pressed_color;
|
||||
Color font_hover_color;
|
||||
Color font_hover_pressed_color;
|
||||
Color font_disabled_color;
|
||||
|
||||
Ref<Font> font;
|
||||
int font_size = 0;
|
||||
int outline_size = 0;
|
||||
Color font_outline_color;
|
||||
|
||||
Color icon_normal_color;
|
||||
Color icon_focus_color;
|
||||
Color icon_pressed_color;
|
||||
Color icon_hover_color;
|
||||
Color icon_hover_pressed_color;
|
||||
Color icon_disabled_color;
|
||||
|
||||
Ref<Texture2D> icon;
|
||||
|
||||
int h_separation = 0;
|
||||
} theme_cache;
|
||||
|
||||
void _shape(Ref<TextParagraph> p_paragraph = Ref<TextParagraph>(), String p_text = "");
|
||||
|
||||
protected:
|
||||
void _set_internal_margin(Side p_side, float p_value);
|
||||
virtual void _update_theme_item_cache() override;
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
|
@ -33,39 +33,30 @@
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
Size2 CheckBox::get_icon_size() const {
|
||||
Ref<Texture2D> checked = Control::get_theme_icon(SNAME("checked"));
|
||||
Ref<Texture2D> unchecked = Control::get_theme_icon(SNAME("unchecked"));
|
||||
Ref<Texture2D> radio_checked = Control::get_theme_icon(SNAME("radio_checked"));
|
||||
Ref<Texture2D> radio_unchecked = Control::get_theme_icon(SNAME("radio_unchecked"));
|
||||
Ref<Texture2D> checked_disabled = Control::get_theme_icon(SNAME("checked_disabled"));
|
||||
Ref<Texture2D> unchecked_disabled = Control::get_theme_icon(SNAME("unchecked_disabled"));
|
||||
Ref<Texture2D> radio_checked_disabled = Control::get_theme_icon(SNAME("radio_checked_disabled"));
|
||||
Ref<Texture2D> radio_unchecked_disabled = Control::get_theme_icon(SNAME("radio_unchecked_disabled"));
|
||||
|
||||
Size2 tex_size = Size2(0, 0);
|
||||
if (!checked.is_null()) {
|
||||
tex_size = Size2(checked->get_width(), checked->get_height());
|
||||
if (!theme_cache.checked.is_null()) {
|
||||
tex_size = Size2(theme_cache.checked->get_width(), theme_cache.checked->get_height());
|
||||
}
|
||||
if (!unchecked.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, unchecked->get_width()), MAX(tex_size.height, unchecked->get_height()));
|
||||
if (!theme_cache.unchecked.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, theme_cache.unchecked->get_width()), MAX(tex_size.height, theme_cache.unchecked->get_height()));
|
||||
}
|
||||
if (!radio_checked.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, radio_checked->get_width()), MAX(tex_size.height, radio_checked->get_height()));
|
||||
if (!theme_cache.radio_checked.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, theme_cache.radio_checked->get_width()), MAX(tex_size.height, theme_cache.radio_checked->get_height()));
|
||||
}
|
||||
if (!radio_unchecked.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, radio_unchecked->get_width()), MAX(tex_size.height, radio_unchecked->get_height()));
|
||||
if (!theme_cache.radio_unchecked.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, theme_cache.radio_unchecked->get_width()), MAX(tex_size.height, theme_cache.radio_unchecked->get_height()));
|
||||
}
|
||||
if (!checked_disabled.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, checked_disabled->get_width()), MAX(tex_size.height, checked_disabled->get_height()));
|
||||
if (!theme_cache.checked_disabled.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, theme_cache.checked_disabled->get_width()), MAX(tex_size.height, theme_cache.checked_disabled->get_height()));
|
||||
}
|
||||
if (!unchecked_disabled.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, unchecked_disabled->get_width()), MAX(tex_size.height, unchecked_disabled->get_height()));
|
||||
if (!theme_cache.unchecked_disabled.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, theme_cache.unchecked_disabled->get_width()), MAX(tex_size.height, theme_cache.unchecked_disabled->get_height()));
|
||||
}
|
||||
if (!radio_checked_disabled.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, radio_checked_disabled->get_width()), MAX(tex_size.height, radio_checked_disabled->get_height()));
|
||||
if (!theme_cache.radio_checked_disabled.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, theme_cache.radio_checked_disabled->get_width()), MAX(tex_size.height, theme_cache.radio_checked_disabled->get_height()));
|
||||
}
|
||||
if (!radio_unchecked_disabled.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, radio_unchecked_disabled->get_width()), MAX(tex_size.height, radio_unchecked_disabled->get_height()));
|
||||
if (!theme_cache.radio_unchecked_disabled.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, theme_cache.radio_unchecked_disabled->get_width()), MAX(tex_size.height, theme_cache.radio_unchecked_disabled->get_height()));
|
||||
}
|
||||
return tex_size;
|
||||
}
|
||||
@ -75,14 +66,30 @@ Size2 CheckBox::get_minimum_size() const {
|
||||
Size2 tex_size = get_icon_size();
|
||||
minsize.width += tex_size.width;
|
||||
if (get_text().length() > 0) {
|
||||
minsize.width += MAX(0, get_theme_constant(SNAME("h_separation")));
|
||||
minsize.width += MAX(0, theme_cache.h_separation);
|
||||
}
|
||||
Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
|
||||
minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(SIDE_TOP) + sb->get_margin(SIDE_BOTTOM));
|
||||
minsize.height = MAX(minsize.height, tex_size.height + theme_cache.normal_style->get_margin(SIDE_TOP) + theme_cache.normal_style->get_margin(SIDE_BOTTOM));
|
||||
|
||||
return minsize;
|
||||
}
|
||||
|
||||
void CheckBox::_update_theme_item_cache() {
|
||||
Button::_update_theme_item_cache();
|
||||
|
||||
theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
|
||||
theme_cache.check_v_adjust = get_theme_constant(SNAME("check_v_adjust"));
|
||||
theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
|
||||
|
||||
theme_cache.checked = get_theme_icon(SNAME("checked"));
|
||||
theme_cache.unchecked = get_theme_icon(SNAME("unchecked"));
|
||||
theme_cache.radio_checked = get_theme_icon(SNAME("radio_checked"));
|
||||
theme_cache.radio_unchecked = get_theme_icon(SNAME("radio_unchecked"));
|
||||
theme_cache.checked_disabled = get_theme_icon(SNAME("checked_disabled"));
|
||||
theme_cache.unchecked_disabled = get_theme_icon(SNAME("unchecked_disabled"));
|
||||
theme_cache.radio_checked_disabled = get_theme_icon(SNAME("radio_checked_disabled"));
|
||||
theme_cache.radio_unchecked_disabled = get_theme_icon(SNAME("radio_unchecked_disabled"));
|
||||
}
|
||||
|
||||
void CheckBox::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_THEME_CHANGED:
|
||||
@ -100,22 +107,39 @@ void CheckBox::_notification(int p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
RID ci = get_canvas_item();
|
||||
|
||||
Ref<Texture2D> on = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_checked" : "checked", is_disabled() ? "_disabled" : ""));
|
||||
Ref<Texture2D> off = Control::get_theme_icon(vformat("%s%s", is_radio() ? "radio_unchecked" : "unchecked", is_disabled() ? "_disabled" : ""));
|
||||
Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
|
||||
Ref<Texture2D> on_tex;
|
||||
Ref<Texture2D> off_tex;
|
||||
|
||||
if (is_radio()) {
|
||||
if (is_disabled()) {
|
||||
on_tex = theme_cache.radio_checked_disabled;
|
||||
off_tex = theme_cache.radio_unchecked_disabled;
|
||||
} else {
|
||||
on_tex = theme_cache.radio_checked;
|
||||
off_tex = theme_cache.radio_unchecked;
|
||||
}
|
||||
} else {
|
||||
if (is_disabled()) {
|
||||
on_tex = theme_cache.checked_disabled;
|
||||
off_tex = theme_cache.unchecked_disabled;
|
||||
} else {
|
||||
on_tex = theme_cache.checked;
|
||||
off_tex = theme_cache.unchecked;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 ofs;
|
||||
if (is_layout_rtl()) {
|
||||
ofs.x = get_size().x - sb->get_margin(SIDE_RIGHT) - get_icon_size().width;
|
||||
ofs.x = get_size().x - theme_cache.normal_style->get_margin(SIDE_RIGHT) - get_icon_size().width;
|
||||
} else {
|
||||
ofs.x = sb->get_margin(SIDE_LEFT);
|
||||
ofs.x = theme_cache.normal_style->get_margin(SIDE_LEFT);
|
||||
}
|
||||
ofs.y = int((get_size().height - get_icon_size().height) / 2) + get_theme_constant(SNAME("check_v_adjust"));
|
||||
ofs.y = int((get_size().height - get_icon_size().height) / 2) + theme_cache.check_v_adjust;
|
||||
|
||||
if (is_pressed()) {
|
||||
on->draw(ci, ofs);
|
||||
on_tex->draw(ci, ofs);
|
||||
} else {
|
||||
off->draw(ci, ofs);
|
||||
off_tex->draw(ci, ofs);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -36,9 +36,26 @@
|
||||
class CheckBox : public Button {
|
||||
GDCLASS(CheckBox, Button);
|
||||
|
||||
struct ThemeCache {
|
||||
int h_separation = 0;
|
||||
int check_v_adjust = 0;
|
||||
Ref<StyleBox> normal_style;
|
||||
|
||||
Ref<Texture2D> checked;
|
||||
Ref<Texture2D> unchecked;
|
||||
Ref<Texture2D> radio_checked;
|
||||
Ref<Texture2D> radio_unchecked;
|
||||
Ref<Texture2D> checked_disabled;
|
||||
Ref<Texture2D> unchecked_disabled;
|
||||
Ref<Texture2D> radio_checked_disabled;
|
||||
Ref<Texture2D> radio_unchecked_disabled;
|
||||
} theme_cache;
|
||||
|
||||
protected:
|
||||
Size2 get_icon_size() const;
|
||||
Size2 get_minimum_size() const override;
|
||||
|
||||
virtual void _update_theme_item_cache() override;
|
||||
void _notification(int p_what);
|
||||
|
||||
bool is_radio();
|
||||
|
@ -34,14 +34,33 @@
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
Size2 CheckButton::get_icon_size() const {
|
||||
Ref<Texture2D> on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on");
|
||||
Ref<Texture2D> off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off");
|
||||
Size2 tex_size = Size2(0, 0);
|
||||
if (!on.is_null()) {
|
||||
tex_size = Size2(on->get_width(), on->get_height());
|
||||
Ref<Texture2D> on_tex;
|
||||
Ref<Texture2D> off_tex;
|
||||
|
||||
if (is_layout_rtl()) {
|
||||
if (is_disabled()) {
|
||||
on_tex = theme_cache.checked_disabled_mirrored;
|
||||
off_tex = theme_cache.unchecked_disabled_mirrored;
|
||||
} else {
|
||||
on_tex = theme_cache.checked_mirrored;
|
||||
off_tex = theme_cache.unchecked_mirrored;
|
||||
}
|
||||
} else {
|
||||
if (is_disabled()) {
|
||||
on_tex = theme_cache.checked_disabled;
|
||||
off_tex = theme_cache.unchecked_disabled;
|
||||
} else {
|
||||
on_tex = theme_cache.checked;
|
||||
off_tex = theme_cache.unchecked;
|
||||
}
|
||||
}
|
||||
if (!off.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, off->get_width()), MAX(tex_size.height, off->get_height()));
|
||||
|
||||
Size2 tex_size = Size2(0, 0);
|
||||
if (!on_tex.is_null()) {
|
||||
tex_size = Size2(on_tex->get_width(), on_tex->get_height());
|
||||
}
|
||||
if (!off_tex.is_null()) {
|
||||
tex_size = Size2(MAX(tex_size.width, off_tex->get_width()), MAX(tex_size.height, off_tex->get_height()));
|
||||
}
|
||||
|
||||
return tex_size;
|
||||
@ -52,14 +71,30 @@ Size2 CheckButton::get_minimum_size() const {
|
||||
Size2 tex_size = get_icon_size();
|
||||
minsize.width += tex_size.width;
|
||||
if (get_text().length() > 0) {
|
||||
minsize.width += MAX(0, get_theme_constant(SNAME("h_separation")));
|
||||
minsize.width += MAX(0, theme_cache.h_separation);
|
||||
}
|
||||
Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
|
||||
minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(SIDE_TOP) + sb->get_margin(SIDE_BOTTOM));
|
||||
minsize.height = MAX(minsize.height, tex_size.height + theme_cache.normal_style->get_margin(SIDE_TOP) + theme_cache.normal_style->get_margin(SIDE_BOTTOM));
|
||||
|
||||
return minsize;
|
||||
}
|
||||
|
||||
void CheckButton::_update_theme_item_cache() {
|
||||
Button::_update_theme_item_cache();
|
||||
|
||||
theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
|
||||
theme_cache.check_v_adjust = get_theme_constant(SNAME("check_v_adjust"));
|
||||
theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
|
||||
|
||||
theme_cache.checked = get_theme_icon(SNAME("on"));
|
||||
theme_cache.unchecked = get_theme_icon(SNAME("off"));
|
||||
theme_cache.checked_disabled = get_theme_icon(SNAME("on_disabled"));
|
||||
theme_cache.unchecked_disabled = get_theme_icon(SNAME("off_disabled"));
|
||||
theme_cache.checked_mirrored = get_theme_icon(SNAME("on_mirrored"));
|
||||
theme_cache.unchecked_mirrored = get_theme_icon(SNAME("off_mirrored"));
|
||||
theme_cache.checked_disabled_mirrored = get_theme_icon(SNAME("on_disabled_mirrored"));
|
||||
theme_cache.unchecked_disabled_mirrored = get_theme_icon(SNAME("off_disabled_mirrored"));
|
||||
}
|
||||
|
||||
void CheckButton::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_THEME_CHANGED:
|
||||
@ -78,34 +113,41 @@ void CheckButton::_notification(int p_what) {
|
||||
RID ci = get_canvas_item();
|
||||
bool rtl = is_layout_rtl();
|
||||
|
||||
Ref<Texture2D> on;
|
||||
Ref<Texture2D> on_tex;
|
||||
Ref<Texture2D> off_tex;
|
||||
|
||||
if (rtl) {
|
||||
on = Control::get_theme_icon(is_disabled() ? "on_disabled_mirrored" : "on_mirrored");
|
||||
if (is_disabled()) {
|
||||
on_tex = theme_cache.checked_disabled_mirrored;
|
||||
off_tex = theme_cache.unchecked_disabled_mirrored;
|
||||
} else {
|
||||
on_tex = theme_cache.checked_mirrored;
|
||||
off_tex = theme_cache.unchecked_mirrored;
|
||||
}
|
||||
} else {
|
||||
on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on");
|
||||
}
|
||||
Ref<Texture2D> off;
|
||||
if (rtl) {
|
||||
off = Control::get_theme_icon(is_disabled() ? "off_disabled_mirrored" : "off_mirrored");
|
||||
} else {
|
||||
off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off");
|
||||
if (is_disabled()) {
|
||||
on_tex = theme_cache.checked_disabled;
|
||||
off_tex = theme_cache.unchecked_disabled;
|
||||
} else {
|
||||
on_tex = theme_cache.checked;
|
||||
off_tex = theme_cache.unchecked;
|
||||
}
|
||||
}
|
||||
|
||||
Ref<StyleBox> sb = get_theme_stylebox(SNAME("normal"));
|
||||
Vector2 ofs;
|
||||
Size2 tex_size = get_icon_size();
|
||||
|
||||
if (rtl) {
|
||||
ofs.x = sb->get_margin(SIDE_LEFT);
|
||||
ofs.x = theme_cache.normal_style->get_margin(SIDE_LEFT);
|
||||
} else {
|
||||
ofs.x = get_size().width - (tex_size.width + sb->get_margin(SIDE_RIGHT));
|
||||
ofs.x = get_size().width - (tex_size.width + theme_cache.normal_style->get_margin(SIDE_RIGHT));
|
||||
}
|
||||
ofs.y = (get_size().height - tex_size.height) / 2 + get_theme_constant(SNAME("check_v_adjust"));
|
||||
ofs.y = (get_size().height - tex_size.height) / 2 + theme_cache.check_v_adjust;
|
||||
|
||||
if (is_pressed()) {
|
||||
on->draw(ci, ofs);
|
||||
on_tex->draw(ci, ofs);
|
||||
} else {
|
||||
off->draw(ci, ofs);
|
||||
off_tex->draw(ci, ofs);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -36,9 +36,26 @@
|
||||
class CheckButton : public Button {
|
||||
GDCLASS(CheckButton, Button);
|
||||
|
||||
struct ThemeCache {
|
||||
int h_separation = 0;
|
||||
int check_v_adjust = 0;
|
||||
Ref<StyleBox> normal_style;
|
||||
|
||||
Ref<Texture2D> checked;
|
||||
Ref<Texture2D> unchecked;
|
||||
Ref<Texture2D> checked_disabled;
|
||||
Ref<Texture2D> unchecked_disabled;
|
||||
Ref<Texture2D> checked_mirrored;
|
||||
Ref<Texture2D> unchecked_mirrored;
|
||||
Ref<Texture2D> checked_disabled_mirrored;
|
||||
Ref<Texture2D> unchecked_disabled_mirrored;
|
||||
} theme_cache;
|
||||
|
||||
protected:
|
||||
Size2 get_icon_size() const;
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
|
||||
virtual void _update_theme_item_cache() override;
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
|
@ -2330,6 +2330,9 @@ void Control::_invalidate_theme_cache() {
|
||||
data.theme_constant_cache.clear();
|
||||
}
|
||||
|
||||
void Control::_update_theme_item_cache() {
|
||||
}
|
||||
|
||||
void Control::set_theme(const Ref<Theme> &p_theme) {
|
||||
if (data.theme == p_theme) {
|
||||
return;
|
||||
@ -3103,6 +3106,11 @@ void Control::remove_child_notify(Node *p_child) {
|
||||
|
||||
void Control::_notification(int p_notification) {
|
||||
switch (p_notification) {
|
||||
case NOTIFICATION_POSTINITIALIZE: {
|
||||
_invalidate_theme_cache();
|
||||
_update_theme_item_cache();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
// Need to defer here, because theme owner information might be set in
|
||||
// add_child_notify, which doesn't get called until right after this.
|
||||
@ -3236,6 +3244,7 @@ void Control::_notification(int p_notification) {
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
emit_signal(SceneStringNames::get_singleton()->theme_changed);
|
||||
_invalidate_theme_cache();
|
||||
_update_theme_item_cache();
|
||||
update_minimum_size();
|
||||
queue_redraw();
|
||||
} break;
|
||||
@ -3257,6 +3266,7 @@ void Control::_notification(int p_notification) {
|
||||
if (is_inside_tree()) {
|
||||
data.is_rtl_dirty = true;
|
||||
_invalidate_theme_cache();
|
||||
_update_theme_item_cache();
|
||||
_size_changed();
|
||||
}
|
||||
} break;
|
||||
|
@ -325,6 +325,10 @@ protected:
|
||||
bool _property_can_revert(const StringName &p_name) const;
|
||||
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
|
||||
|
||||
// Theming.
|
||||
|
||||
virtual void _update_theme_item_cache();
|
||||
|
||||
// Internationalization.
|
||||
|
||||
virtual TypedArray<Vector2i> structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
|
||||
|
@ -44,9 +44,6 @@ void FlowContainer::_resort() {
|
||||
return;
|
||||
}
|
||||
|
||||
int separation_horizontal = get_theme_constant(SNAME("h_separation"));
|
||||
int separation_vertical = get_theme_constant(SNAME("v_separation"));
|
||||
|
||||
bool rtl = is_layout_rtl();
|
||||
|
||||
HashMap<Control *, Size2i> children_minsize_cache;
|
||||
@ -74,14 +71,14 @@ void FlowContainer::_resort() {
|
||||
|
||||
if (vertical) { /* VERTICAL */
|
||||
if (children_in_current_line > 0) {
|
||||
ofs.y += separation_vertical;
|
||||
ofs.y += theme_cache.v_separation;
|
||||
}
|
||||
if (ofs.y + child_msc.y > current_container_size) {
|
||||
line_length = ofs.y - separation_vertical;
|
||||
line_length = ofs.y - theme_cache.v_separation;
|
||||
lines_data.push_back(_LineData{ children_in_current_line, line_height, line_length, current_container_size - line_length, line_stretch_ratio_total });
|
||||
|
||||
// Move in new column (vertical line).
|
||||
ofs.x += line_height + separation_horizontal;
|
||||
ofs.x += line_height + theme_cache.h_separation;
|
||||
ofs.y = 0;
|
||||
line_height = 0;
|
||||
line_stretch_ratio_total = 0;
|
||||
@ -96,14 +93,14 @@ void FlowContainer::_resort() {
|
||||
|
||||
} else { /* HORIZONTAL */
|
||||
if (children_in_current_line > 0) {
|
||||
ofs.x += separation_horizontal;
|
||||
ofs.x += theme_cache.h_separation;
|
||||
}
|
||||
if (ofs.x + child_msc.x > current_container_size) {
|
||||
line_length = ofs.x - separation_horizontal;
|
||||
line_length = ofs.x - theme_cache.h_separation;
|
||||
lines_data.push_back(_LineData{ children_in_current_line, line_height, line_length, current_container_size - line_length, line_stretch_ratio_total });
|
||||
|
||||
// Move in new line.
|
||||
ofs.y += line_height + separation_vertical;
|
||||
ofs.y += line_height + theme_cache.v_separation;
|
||||
ofs.x = 0;
|
||||
line_height = 0;
|
||||
line_stretch_ratio_total = 0;
|
||||
@ -146,11 +143,11 @@ void FlowContainer::_resort() {
|
||||
current_line_idx++;
|
||||
child_idx_in_line = 0;
|
||||
if (vertical) {
|
||||
ofs.x += line_data.min_line_height + separation_horizontal;
|
||||
ofs.x += line_data.min_line_height + theme_cache.h_separation;
|
||||
ofs.y = 0;
|
||||
} else {
|
||||
ofs.x = 0;
|
||||
ofs.y += line_data.min_line_height + separation_vertical;
|
||||
ofs.y += line_data.min_line_height + theme_cache.v_separation;
|
||||
}
|
||||
line_data = lines_data[current_line_idx];
|
||||
}
|
||||
@ -184,9 +181,9 @@ void FlowContainer::_resort() {
|
||||
fit_child_in_rect(child, child_rect);
|
||||
|
||||
if (vertical) { /* VERTICAL */
|
||||
ofs.y += child_size.height + separation_vertical;
|
||||
ofs.y += child_size.height + theme_cache.v_separation;
|
||||
} else { /* HORIZONTAL */
|
||||
ofs.x += child_size.width + separation_horizontal;
|
||||
ofs.x += child_size.width + theme_cache.h_separation;
|
||||
}
|
||||
|
||||
child_idx_in_line++;
|
||||
@ -250,6 +247,13 @@ Vector<int> FlowContainer::get_allowed_size_flags_vertical() const {
|
||||
return flags;
|
||||
}
|
||||
|
||||
void FlowContainer::_update_theme_item_cache() {
|
||||
Container::_update_theme_item_cache();
|
||||
|
||||
theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
|
||||
theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
|
||||
}
|
||||
|
||||
void FlowContainer::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_SORT_CHILDREN: {
|
||||
|
@ -42,11 +42,17 @@ private:
|
||||
|
||||
bool vertical = false;
|
||||
|
||||
struct ThemeCache {
|
||||
int h_separation = 0;
|
||||
int v_separation = 0;
|
||||
} theme_cache;
|
||||
|
||||
void _resort();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
@ -31,6 +31,13 @@
|
||||
#include "grid_container.h"
|
||||
#include "core/templates/rb_set.h"
|
||||
|
||||
void GridContainer::_update_theme_item_cache() {
|
||||
Container::_update_theme_item_cache();
|
||||
|
||||
theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
|
||||
theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
|
||||
}
|
||||
|
||||
void GridContainer::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_SORT_CHILDREN: {
|
||||
@ -39,9 +46,6 @@ void GridContainer::_notification(int p_what) {
|
||||
RBSet<int> col_expanded; // Columns which have the SIZE_EXPAND flag set.
|
||||
RBSet<int> row_expanded; // Rows which have the SIZE_EXPAND flag set.
|
||||
|
||||
int hsep = get_theme_constant(SNAME("h_separation"));
|
||||
int vsep = get_theme_constant(SNAME("v_separation"));
|
||||
|
||||
// Compute the per-column/per-row data.
|
||||
int valid_controls_index = 0;
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
@ -98,8 +102,8 @@ void GridContainer::_notification(int p_what) {
|
||||
remaining_space.height -= E.value;
|
||||
}
|
||||
}
|
||||
remaining_space.height -= vsep * MAX(max_row - 1, 0);
|
||||
remaining_space.width -= hsep * MAX(max_col - 1, 0);
|
||||
remaining_space.height -= theme_cache.v_separation * MAX(max_row - 1, 0);
|
||||
remaining_space.width -= theme_cache.h_separation * MAX(max_col - 1, 0);
|
||||
|
||||
bool can_fit = false;
|
||||
while (!can_fit && col_expanded.size() > 0) {
|
||||
@ -202,7 +206,7 @@ void GridContainer::_notification(int p_what) {
|
||||
col_ofs = 0;
|
||||
}
|
||||
if (row > 0) {
|
||||
row_ofs += (row_expanded.has(row - 1) ? row_expand : row_minh[row - 1]) + vsep;
|
||||
row_ofs += (row_expanded.has(row - 1) ? row_expand : row_minh[row - 1]) + theme_cache.v_separation;
|
||||
|
||||
if (row_expanded.has(row - 1) && row - 1 < row_remaining_pixel_index) {
|
||||
// Apply the remaining pixel of the previous row.
|
||||
@ -224,11 +228,11 @@ void GridContainer::_notification(int p_what) {
|
||||
if (rtl) {
|
||||
Point2 p(col_ofs - s.width, row_ofs);
|
||||
fit_child_in_rect(c, Rect2(p, s));
|
||||
col_ofs -= s.width + hsep;
|
||||
col_ofs -= s.width + theme_cache.h_separation;
|
||||
} else {
|
||||
Point2 p(col_ofs, row_ofs);
|
||||
fit_child_in_rect(c, Rect2(p, s));
|
||||
col_ofs += s.width + hsep;
|
||||
col_ofs += s.width + theme_cache.h_separation;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@ -271,9 +275,6 @@ Size2 GridContainer::get_minimum_size() const {
|
||||
RBMap<int, int> col_minw;
|
||||
RBMap<int, int> row_minh;
|
||||
|
||||
int hsep = get_theme_constant(SNAME("h_separation"));
|
||||
int vsep = get_theme_constant(SNAME("v_separation"));
|
||||
|
||||
int max_row = 0;
|
||||
int max_col = 0;
|
||||
|
||||
@ -313,8 +314,8 @@ Size2 GridContainer::get_minimum_size() const {
|
||||
ms.height += E.value;
|
||||
}
|
||||
|
||||
ms.height += vsep * max_row;
|
||||
ms.width += hsep * max_col;
|
||||
ms.height += theme_cache.v_separation * max_row;
|
||||
ms.width += theme_cache.h_separation * max_col;
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
@ -38,7 +38,14 @@ class GridContainer : public Container {
|
||||
|
||||
int columns = 1;
|
||||
|
||||
struct ThemeCache {
|
||||
int h_separation = 0;
|
||||
int v_separation = 0;
|
||||
} theme_cache;
|
||||
|
||||
protected:
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
|
@ -43,7 +43,7 @@ void ItemList::_shape(int p_idx) {
|
||||
} else {
|
||||
item.text_buf->set_direction((TextServer::Direction)item.text_direction);
|
||||
}
|
||||
item.text_buf->add_string(item.text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), item.language);
|
||||
item.text_buf->add_string(item.text, theme_cache.font, theme_cache.font_size, item.language);
|
||||
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
|
||||
item.text_buf->set_break_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_TRIM_EDGE_SPACES);
|
||||
} else {
|
||||
@ -655,8 +655,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) {
|
||||
if (mb.is_valid() && mb->is_pressed()) {
|
||||
search_string = ""; //any mousepress cancels
|
||||
Vector2 pos = mb->get_position();
|
||||
Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
|
||||
pos -= bg->get_offset();
|
||||
pos -= theme_cache.bg_style->get_offset();
|
||||
pos.y += scroll_bar->get_value();
|
||||
|
||||
if (is_layout_rtl()) {
|
||||
@ -980,6 +979,31 @@ static Rect2 _adjust_to_max_size(Size2 p_size, Size2 p_max_size) {
|
||||
return Rect2(ofs_x, ofs_y, tex_width, tex_height);
|
||||
}
|
||||
|
||||
void ItemList::_update_theme_item_cache() {
|
||||
Control::_update_theme_item_cache();
|
||||
|
||||
theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
|
||||
theme_cache.v_separation = get_theme_constant(SNAME("v_separation"));
|
||||
|
||||
theme_cache.bg_style = get_theme_stylebox(SNAME("bg"));
|
||||
theme_cache.bg_focus_style = get_theme_stylebox(SNAME("bg_focus"));
|
||||
|
||||
theme_cache.font = get_theme_font(SNAME("font"));
|
||||
theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
|
||||
theme_cache.font_color = get_theme_color(SNAME("font_color"));
|
||||
theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
|
||||
theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
|
||||
theme_cache.line_separation = get_theme_constant(SNAME("line_separation"));
|
||||
theme_cache.icon_margin = get_theme_constant(SNAME("icon_margin"));
|
||||
theme_cache.selected_style = get_theme_stylebox(SNAME("selected"));
|
||||
theme_cache.selected_focus_style = get_theme_stylebox(SNAME("selected_focus"));
|
||||
theme_cache.cursor_style = get_theme_stylebox(SNAME("cursor_unfocused"));
|
||||
theme_cache.cursor_focus_style = get_theme_stylebox(SNAME("cursor"));
|
||||
theme_cache.guide_color = get_theme_color(SNAME("guide_color"));
|
||||
}
|
||||
|
||||
void ItemList::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_RESIZED: {
|
||||
@ -998,37 +1022,32 @@ void ItemList::_notification(int p_what) {
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_DRAW: {
|
||||
Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
|
||||
|
||||
int mw = scroll_bar->get_minimum_size().x;
|
||||
scroll_bar->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -mw);
|
||||
scroll_bar->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, 0);
|
||||
scroll_bar->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, bg->get_margin(SIDE_TOP));
|
||||
scroll_bar->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -bg->get_margin(SIDE_BOTTOM));
|
||||
scroll_bar->set_anchor_and_offset(SIDE_TOP, ANCHOR_BEGIN, theme_cache.bg_style->get_margin(SIDE_TOP));
|
||||
scroll_bar->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -theme_cache.bg_style->get_margin(SIDE_BOTTOM));
|
||||
|
||||
Size2 size = get_size();
|
||||
int width = size.width - bg->get_minimum_size().width;
|
||||
int width = size.width - theme_cache.bg_style->get_minimum_size().width;
|
||||
|
||||
draw_style_box(bg, Rect2(Point2(), size));
|
||||
draw_style_box(theme_cache.bg_style, Rect2(Point2(), size));
|
||||
|
||||
int hseparation = get_theme_constant(SNAME("h_separation"));
|
||||
int vseparation = get_theme_constant(SNAME("v_separation"));
|
||||
int icon_margin = get_theme_constant(SNAME("icon_margin"));
|
||||
int line_separation = get_theme_constant(SNAME("line_separation"));
|
||||
Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
int outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
Ref<StyleBox> sbsel;
|
||||
Ref<StyleBox> cursor;
|
||||
|
||||
Ref<StyleBox> sbsel = has_focus() ? get_theme_stylebox(SNAME("selected_focus")) : get_theme_stylebox(SNAME("selected"));
|
||||
Ref<StyleBox> cursor = has_focus() ? get_theme_stylebox(SNAME("cursor")) : get_theme_stylebox(SNAME("cursor_unfocused"));
|
||||
if (has_focus()) {
|
||||
sbsel = theme_cache.selected_focus_style;
|
||||
cursor = theme_cache.cursor_focus_style;
|
||||
} else {
|
||||
sbsel = theme_cache.selected_style;
|
||||
cursor = theme_cache.cursor_style;
|
||||
}
|
||||
bool rtl = is_layout_rtl();
|
||||
|
||||
Color guide_color = get_theme_color(SNAME("guide_color"));
|
||||
Color font_color = get_theme_color(SNAME("font_color"));
|
||||
Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
|
||||
|
||||
if (has_focus()) {
|
||||
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), true);
|
||||
draw_style_box(get_theme_stylebox(SNAME("bg_focus")), Rect2(Point2(), size));
|
||||
draw_style_box(theme_cache.bg_focus_style, Rect2(Point2(), size));
|
||||
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), false);
|
||||
}
|
||||
|
||||
@ -1047,9 +1066,9 @@ void ItemList::_notification(int p_what) {
|
||||
|
||||
if (!items[i].text.is_empty()) {
|
||||
if (icon_mode == ICON_MODE_TOP) {
|
||||
minsize.y += icon_margin;
|
||||
minsize.y += theme_cache.icon_margin;
|
||||
} else {
|
||||
minsize.x += icon_margin;
|
||||
minsize.x += theme_cache.icon_margin;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1067,7 +1086,7 @@ void ItemList::_notification(int p_what) {
|
||||
if (icon_mode == ICON_MODE_TOP) {
|
||||
minsize.x = MAX(minsize.x, s.width);
|
||||
if (max_text_lines > 0) {
|
||||
minsize.y += s.height + line_separation * max_text_lines;
|
||||
minsize.y += s.height + theme_cache.line_separation * max_text_lines;
|
||||
} else {
|
||||
minsize.y += s.height;
|
||||
}
|
||||
@ -1084,13 +1103,13 @@ void ItemList::_notification(int p_what) {
|
||||
max_column_width = MAX(max_column_width, minsize.x);
|
||||
|
||||
// elements need to adapt to the selected size
|
||||
minsize.y += vseparation;
|
||||
minsize.x += hseparation;
|
||||
minsize.y += theme_cache.v_separation;
|
||||
minsize.x += theme_cache.h_separation;
|
||||
items.write[i].rect_cache.size = minsize;
|
||||
items.write[i].min_rect_cache.size = minsize;
|
||||
}
|
||||
|
||||
int fit_size = size.x - bg->get_minimum_size().width - mw;
|
||||
int fit_size = size.x - theme_cache.bg_style->get_minimum_size().width - mw;
|
||||
|
||||
//2-attempt best fit
|
||||
current_columns = 0x7FFFFFFF;
|
||||
@ -1118,11 +1137,11 @@ void ItemList::_notification(int p_what) {
|
||||
}
|
||||
items.write[i].rect_cache.position = ofs;
|
||||
max_h = MAX(max_h, items[i].rect_cache.size.y);
|
||||
ofs.x += items[i].rect_cache.size.x + hseparation;
|
||||
ofs.x += items[i].rect_cache.size.x + theme_cache.h_separation;
|
||||
col++;
|
||||
if (col == current_columns) {
|
||||
if (i < items.size() - 1) {
|
||||
separators.push_back(ofs.y + max_h + vseparation / 2);
|
||||
separators.push_back(ofs.y + max_h + theme_cache.v_separation / 2);
|
||||
}
|
||||
|
||||
for (int j = i; j >= 0 && col > 0; j--, col--) {
|
||||
@ -1130,7 +1149,7 @@ void ItemList::_notification(int p_what) {
|
||||
}
|
||||
|
||||
ofs.x = 0;
|
||||
ofs.y += max_h + vseparation;
|
||||
ofs.y += max_h + theme_cache.v_separation;
|
||||
col = 0;
|
||||
max_h = 0;
|
||||
}
|
||||
@ -1141,10 +1160,10 @@ void ItemList::_notification(int p_what) {
|
||||
}
|
||||
|
||||
if (all_fit) {
|
||||
float page = MAX(0, size.height - bg->get_minimum_size().height);
|
||||
float page = MAX(0, size.height - theme_cache.bg_style->get_minimum_size().height);
|
||||
float max = MAX(page, ofs.y + max_h);
|
||||
if (auto_height) {
|
||||
auto_height_value = ofs.y + max_h + bg->get_minimum_size().height;
|
||||
auto_height_value = ofs.y + max_h + theme_cache.bg_style->get_minimum_size().height;
|
||||
}
|
||||
scroll_bar->set_max(max);
|
||||
scroll_bar->set_page(page);
|
||||
@ -1185,7 +1204,7 @@ void ItemList::_notification(int p_what) {
|
||||
|
||||
ensure_selected_visible = false;
|
||||
|
||||
Vector2 base_ofs = bg->get_offset();
|
||||
Vector2 base_ofs = theme_cache.bg_style->get_offset();
|
||||
base_ofs.y -= int(scroll_bar->get_value());
|
||||
|
||||
const Rect2 clip(-base_ofs, size); // visible frame, don't need to draw outside of there
|
||||
@ -1229,10 +1248,10 @@ void ItemList::_notification(int p_what) {
|
||||
if (items[i].selected) {
|
||||
Rect2 r = rcache;
|
||||
r.position += base_ofs;
|
||||
r.position.y -= vseparation / 2;
|
||||
r.size.y += vseparation;
|
||||
r.position.x -= hseparation / 2;
|
||||
r.size.x += hseparation;
|
||||
r.position.y -= theme_cache.v_separation / 2;
|
||||
r.size.y += theme_cache.v_separation;
|
||||
r.position.x -= theme_cache.h_separation / 2;
|
||||
r.size.x += theme_cache.h_separation;
|
||||
|
||||
if (rtl) {
|
||||
r.position.x = size.width - r.position.x - r.size.x;
|
||||
@ -1245,10 +1264,10 @@ void ItemList::_notification(int p_what) {
|
||||
r.position += base_ofs;
|
||||
|
||||
// Size rect to make the align the temperature colors
|
||||
r.position.y -= vseparation / 2;
|
||||
r.size.y += vseparation;
|
||||
r.position.x -= hseparation / 2;
|
||||
r.size.x += hseparation;
|
||||
r.position.y -= theme_cache.v_separation / 2;
|
||||
r.size.y += theme_cache.v_separation;
|
||||
r.position.x -= theme_cache.h_separation / 2;
|
||||
r.size.x += theme_cache.h_separation;
|
||||
|
||||
if (rtl) {
|
||||
r.position.x = size.width - r.position.x - r.size.x;
|
||||
@ -1274,11 +1293,11 @@ void ItemList::_notification(int p_what) {
|
||||
|
||||
if (icon_mode == ICON_MODE_TOP) {
|
||||
pos.x += Math::floor((items[i].rect_cache.size.width - icon_size.width) / 2);
|
||||
pos.y += icon_margin;
|
||||
text_ofs.y = icon_size.height + icon_margin * 2;
|
||||
pos.y += theme_cache.icon_margin;
|
||||
text_ofs.y = icon_size.height + theme_cache.icon_margin * 2;
|
||||
} else {
|
||||
pos.y += Math::floor((items[i].rect_cache.size.height - icon_size.height) / 2);
|
||||
text_ofs.x = icon_size.width + icon_margin;
|
||||
text_ofs.x = icon_size.width + theme_cache.icon_margin;
|
||||
}
|
||||
|
||||
Rect2 draw_rect = Rect2(pos, icon_size);
|
||||
@ -1329,7 +1348,7 @@ void ItemList::_notification(int p_what) {
|
||||
max_len = size2.x;
|
||||
}
|
||||
|
||||
Color modulate = items[i].selected ? font_selected_color : (items[i].custom_fg != Color() ? items[i].custom_fg : font_color);
|
||||
Color modulate = items[i].selected ? theme_cache.font_selected_color : (items[i].custom_fg != Color() ? items[i].custom_fg : theme_cache.font_color);
|
||||
if (items[i].disabled) {
|
||||
modulate.a *= 0.5;
|
||||
}
|
||||
@ -1344,8 +1363,8 @@ void ItemList::_notification(int p_what) {
|
||||
|
||||
items.write[i].text_buf->set_alignment(HORIZONTAL_ALIGNMENT_CENTER);
|
||||
|
||||
if (outline_size > 0 && font_outline_color.a > 0) {
|
||||
items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, outline_size, font_outline_color);
|
||||
if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
|
||||
items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, theme_cache.font_outline_size, theme_cache.font_outline_color);
|
||||
}
|
||||
|
||||
items[i].text_buf->draw(get_canvas_item(), text_ofs, modulate);
|
||||
@ -1375,8 +1394,8 @@ void ItemList::_notification(int p_what) {
|
||||
items.write[i].text_buf->set_alignment(HORIZONTAL_ALIGNMENT_LEFT);
|
||||
}
|
||||
|
||||
if (outline_size > 0 && font_outline_color.a > 0) {
|
||||
items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, outline_size, font_outline_color);
|
||||
if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
|
||||
items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, theme_cache.font_outline_size, theme_cache.font_outline_color);
|
||||
}
|
||||
|
||||
if (width - text_ofs.x > 0) {
|
||||
@ -1388,10 +1407,10 @@ void ItemList::_notification(int p_what) {
|
||||
if (select_mode == SELECT_MULTI && i == current) {
|
||||
Rect2 r = rcache;
|
||||
r.position += base_ofs;
|
||||
r.position.y -= vseparation / 2;
|
||||
r.size.y += vseparation;
|
||||
r.position.x -= hseparation / 2;
|
||||
r.size.x += hseparation;
|
||||
r.position.y -= theme_cache.v_separation / 2;
|
||||
r.size.y += theme_cache.v_separation;
|
||||
r.position.x -= theme_cache.h_separation / 2;
|
||||
r.size.x += theme_cache.h_separation;
|
||||
|
||||
if (rtl) {
|
||||
r.position.x = size.width - r.position.x - r.size.x;
|
||||
@ -1423,7 +1442,7 @@ void ItemList::_notification(int p_what) {
|
||||
}
|
||||
|
||||
const int y = base_ofs.y + separators[i];
|
||||
draw_line(Vector2(bg->get_margin(SIDE_LEFT), y), Vector2(width, y), guide_color);
|
||||
draw_line(Vector2(theme_cache.bg_style->get_margin(SIDE_LEFT), y), Vector2(width, y), theme_cache.guide_color);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
@ -1435,8 +1454,7 @@ void ItemList::_scroll_changed(double) {
|
||||
|
||||
int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const {
|
||||
Vector2 pos = p_pos;
|
||||
Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
|
||||
pos -= bg->get_offset();
|
||||
pos -= theme_cache.bg_style->get_offset();
|
||||
pos.y += scroll_bar->get_value();
|
||||
|
||||
if (is_layout_rtl()) {
|
||||
@ -1473,8 +1491,7 @@ bool ItemList::is_pos_at_end_of_items(const Point2 &p_pos) const {
|
||||
}
|
||||
|
||||
Vector2 pos = p_pos;
|
||||
Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
|
||||
pos -= bg->get_offset();
|
||||
pos -= theme_cache.bg_style->get_offset();
|
||||
pos.y += scroll_bar->get_value();
|
||||
|
||||
if (is_layout_rtl()) {
|
||||
|
@ -109,23 +109,45 @@ private:
|
||||
int max_columns = 1;
|
||||
|
||||
Size2 fixed_icon_size;
|
||||
|
||||
Size2 max_item_size_cache;
|
||||
|
||||
int defer_select_single = -1;
|
||||
|
||||
bool allow_rmb_select = false;
|
||||
|
||||
bool allow_reselect = false;
|
||||
|
||||
real_t icon_scale = 1.0;
|
||||
|
||||
bool do_autoscroll_to_bottom = false;
|
||||
|
||||
struct ThemeCache {
|
||||
int h_separation = 0;
|
||||
int v_separation = 0;
|
||||
|
||||
Ref<StyleBox> bg_style;
|
||||
Ref<StyleBox> bg_focus_style;
|
||||
|
||||
Ref<Font> font;
|
||||
int font_size = 0;
|
||||
Color font_color;
|
||||
Color font_selected_color;
|
||||
int font_outline_size = 0;
|
||||
Color font_outline_color;
|
||||
|
||||
int line_separation = 0;
|
||||
int icon_margin = 0;
|
||||
Ref<StyleBox> selected_style;
|
||||
Ref<StyleBox> selected_focus_style;
|
||||
Ref<StyleBox> cursor_style;
|
||||
Ref<StyleBox> cursor_focus_style;
|
||||
Color guide_color;
|
||||
} theme_cache;
|
||||
|
||||
void _scroll_changed(double);
|
||||
void _shape(int p_idx);
|
||||
|
||||
protected:
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
|
@ -71,7 +71,7 @@ bool Label::is_uppercase() const {
|
||||
}
|
||||
|
||||
int Label::get_line_height(int p_line) const {
|
||||
Ref<Font> font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
|
||||
Ref<Font> font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
|
||||
if (p_line >= 0 && p_line < lines_rid.size()) {
|
||||
return TS->shaped_text_get_size(lines_rid[p_line]).y;
|
||||
} else if (lines_rid.size() > 0) {
|
||||
@ -81,13 +81,13 @@ int Label::get_line_height(int p_line) const {
|
||||
}
|
||||
return h;
|
||||
} else {
|
||||
int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size"));
|
||||
int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
|
||||
return font->get_height(font_size);
|
||||
}
|
||||
}
|
||||
|
||||
void Label::_shape() {
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"), SNAME("Label"));
|
||||
Ref<StyleBox> style = theme_cache.normal_style;
|
||||
int width = (get_size().width - style->get_minimum_size().width);
|
||||
|
||||
if (dirty || font_dirty) {
|
||||
@ -99,8 +99,8 @@ void Label::_shape() {
|
||||
} else {
|
||||
TS->shaped_text_set_direction(text_rid, (TextServer::Direction)text_direction);
|
||||
}
|
||||
const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
|
||||
int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size"));
|
||||
const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
|
||||
int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
|
||||
ERR_FAIL_COND(font.is_null());
|
||||
String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
|
||||
if (visible_chars >= 0 && visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
|
||||
@ -232,8 +232,8 @@ void Label::_shape() {
|
||||
}
|
||||
|
||||
void Label::_update_visible() {
|
||||
int line_spacing = settings.is_valid() ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"), SNAME("Label"));
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"), SNAME("Label"));
|
||||
int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing;
|
||||
Ref<StyleBox> style = theme_cache.normal_style;
|
||||
int lines_visible = lines_rid.size();
|
||||
|
||||
if (max_lines_visible >= 0 && lines_visible > max_lines_visible) {
|
||||
@ -272,6 +272,22 @@ inline void draw_glyph_outline(const Glyph &p_gl, const RID &p_canvas, const Col
|
||||
}
|
||||
}
|
||||
|
||||
void Label::_update_theme_item_cache() {
|
||||
Control::_update_theme_item_cache();
|
||||
|
||||
theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
|
||||
theme_cache.font = get_theme_font(SNAME("font"));
|
||||
|
||||
theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
|
||||
theme_cache.line_spacing = get_theme_constant(SNAME("line_spacing"));
|
||||
theme_cache.font_color = get_theme_color(SNAME("font_color"));
|
||||
theme_cache.font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
|
||||
theme_cache.font_shadow_offset = Point2(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
|
||||
theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
theme_cache.font_shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size"));
|
||||
}
|
||||
|
||||
void Label::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_TRANSLATION_CHANGED: {
|
||||
@ -307,15 +323,15 @@ void Label::_notification(int p_what) {
|
||||
|
||||
Size2 string_size;
|
||||
Size2 size = get_size();
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
Ref<Font> font = (has_settings && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
|
||||
Color font_color = has_settings ? settings->get_font_color() : get_theme_color(SNAME("font_color"));
|
||||
Color font_shadow_color = has_settings ? settings->get_shadow_color() : get_theme_color(SNAME("font_shadow_color"));
|
||||
Point2 shadow_ofs = has_settings ? settings->get_shadow_offset() : Point2(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
|
||||
int line_spacing = has_settings ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"));
|
||||
Color font_outline_color = has_settings ? settings->get_outline_color() : get_theme_color(SNAME("font_outline_color"));
|
||||
int outline_size = has_settings ? settings->get_outline_size() : get_theme_constant(SNAME("outline_size"));
|
||||
int shadow_outline_size = has_settings ? settings->get_shadow_size() : get_theme_constant(SNAME("shadow_outline_size"));
|
||||
Ref<StyleBox> style = theme_cache.normal_style;
|
||||
Ref<Font> font = (has_settings && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
|
||||
Color font_color = has_settings ? settings->get_font_color() : theme_cache.font_color;
|
||||
Color font_shadow_color = has_settings ? settings->get_shadow_color() : theme_cache.font_shadow_color;
|
||||
Point2 shadow_ofs = has_settings ? settings->get_shadow_offset() : theme_cache.font_shadow_offset;
|
||||
int line_spacing = has_settings ? settings->get_line_spacing() : theme_cache.line_spacing;
|
||||
Color font_outline_color = has_settings ? settings->get_outline_color() : theme_cache.font_outline_color;
|
||||
int outline_size = has_settings ? settings->get_outline_size() : theme_cache.font_outline_size;
|
||||
int shadow_outline_size = has_settings ? settings->get_shadow_size() : theme_cache.font_shadow_outline_size;
|
||||
bool rtl = (TS->shaped_text_get_inferred_direction(text_rid) == TextServer::DIRECTION_RTL);
|
||||
bool rtl_layout = is_layout_rtl();
|
||||
|
||||
@ -562,12 +578,12 @@ Size2 Label::get_minimum_size() const {
|
||||
|
||||
Size2 min_size = minsize;
|
||||
|
||||
const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : get_theme_font(SNAME("font"));
|
||||
int font_size = settings.is_valid() ? settings->get_font_size() : get_theme_font_size(SNAME("font_size"));
|
||||
const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
|
||||
int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
|
||||
|
||||
min_size.height = MAX(min_size.height, font->get_height(font_size) + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM));
|
||||
|
||||
Size2 min_style = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
|
||||
Size2 min_style = theme_cache.normal_style->get_minimum_size();
|
||||
if (autowrap_mode != TextServer::AUTOWRAP_OFF) {
|
||||
return Size2(1, (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) ? 1 : min_size.height) + min_style;
|
||||
} else {
|
||||
@ -590,8 +606,8 @@ int Label::get_line_count() const {
|
||||
}
|
||||
|
||||
int Label::get_visible_line_count() const {
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
int line_spacing = settings.is_valid() ? settings->get_line_spacing() : get_theme_constant(SNAME("line_spacing"));
|
||||
Ref<StyleBox> style = theme_cache.normal_style;
|
||||
int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing;
|
||||
int lines_visible = 0;
|
||||
float total_h = 0.0;
|
||||
for (int64_t i = lines_skipped; i < lines_rid.size(); i++) {
|
||||
|
@ -67,13 +67,28 @@ private:
|
||||
|
||||
Ref<LabelSettings> settings;
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> normal_style;
|
||||
Ref<Font> font;
|
||||
|
||||
int font_size = 0;
|
||||
int line_spacing = 0;
|
||||
Color font_color;
|
||||
Color font_shadow_color;
|
||||
Point2 font_shadow_offset;
|
||||
Color font_outline_color;
|
||||
int font_outline_size;
|
||||
int font_shadow_outline_size;
|
||||
} theme_cache;
|
||||
|
||||
void _update_visible();
|
||||
void _shape();
|
||||
void _invalidate();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
@ -448,7 +448,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
|
||||
if (context_menu_enabled) {
|
||||
if (k->is_action("ui_menu", true)) {
|
||||
_ensure_menu();
|
||||
Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")))) / 2);
|
||||
Point2 pos = Point2(get_caret_pixel_pos().x, (get_size().y + theme_cache.font->get_height(theme_cache.font_size)) / 2);
|
||||
menu->set_position(get_screen_position() + pos);
|
||||
menu->reset_size();
|
||||
menu->popup();
|
||||
@ -696,11 +696,38 @@ bool LineEdit::_is_over_clear_button(const Point2 &p_pos) const {
|
||||
if (!clear_button_enabled || !has_point(p_pos)) {
|
||||
return false;
|
||||
}
|
||||
Ref<Texture2D> icon = Control::get_theme_icon(SNAME("clear"));
|
||||
int x_ofs = get_theme_stylebox(SNAME("normal"))->get_margin(SIDE_RIGHT);
|
||||
Ref<Texture2D> icon = theme_cache.clear_icon;
|
||||
int x_ofs = theme_cache.normal->get_margin(SIDE_RIGHT);
|
||||
return p_pos.x > get_size().width - icon->get_width() - x_ofs;
|
||||
}
|
||||
|
||||
void LineEdit::_update_theme_item_cache() {
|
||||
Control::_update_theme_item_cache();
|
||||
|
||||
theme_cache.normal = get_theme_stylebox(SNAME("normal"));
|
||||
theme_cache.read_only = get_theme_stylebox(SNAME("read_only"));
|
||||
theme_cache.focus = get_theme_stylebox(SNAME("focus"));
|
||||
|
||||
theme_cache.font = get_theme_font(SNAME("font"));
|
||||
theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
|
||||
theme_cache.font_color = get_theme_color(SNAME("font_color"));
|
||||
theme_cache.font_uneditable_color = get_theme_color(SNAME("font_uneditable_color"));
|
||||
theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
|
||||
theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
theme_cache.font_placeholder_color = get_theme_color(SNAME("font_placeholder_color"));
|
||||
theme_cache.caret_width = get_theme_constant(SNAME("caret_width"));
|
||||
theme_cache.caret_color = get_theme_color(SNAME("caret_color"));
|
||||
theme_cache.minimum_character_width = get_theme_constant(SNAME("minimum_character_width"));
|
||||
theme_cache.selection_color = get_theme_color(SNAME("selection_color"));
|
||||
|
||||
theme_cache.clear_icon = get_theme_icon(SNAME("clear"));
|
||||
theme_cache.clear_button_color = get_theme_color(SNAME("clear_button_color"));
|
||||
theme_cache.clear_button_color_pressed = get_theme_color(SNAME("clear_button_color_pressed"));
|
||||
|
||||
theme_cache.base_scale = get_theme_default_base_scale();
|
||||
}
|
||||
|
||||
void LineEdit::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
@ -771,19 +798,19 @@ void LineEdit::_notification(int p_what) {
|
||||
|
||||
RID ci = get_canvas_item();
|
||||
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
Ref<StyleBox> style = theme_cache.normal;
|
||||
if (!is_editable()) {
|
||||
style = get_theme_stylebox(SNAME("read_only"));
|
||||
style = theme_cache.read_only;
|
||||
draw_caret = false;
|
||||
}
|
||||
Ref<Font> font = get_theme_font(SNAME("font"));
|
||||
Ref<Font> font = theme_cache.font;
|
||||
|
||||
if (!flat) {
|
||||
style->draw(ci, Rect2(Point2(), size));
|
||||
}
|
||||
|
||||
if (has_focus()) {
|
||||
get_theme_stylebox(SNAME("focus"))->draw(ci, Rect2(Point2(), size));
|
||||
theme_cache.focus->draw(ci, Rect2(Point2(), size));
|
||||
}
|
||||
|
||||
int x_ofs = 0;
|
||||
@ -821,25 +848,30 @@ void LineEdit::_notification(int p_what) {
|
||||
int y_area = height - style->get_minimum_size().height;
|
||||
int y_ofs = style->get_offset().y + (y_area - text_height) / 2;
|
||||
|
||||
Color selection_color = get_theme_color(SNAME("selection_color"));
|
||||
Color font_color = get_theme_color(is_editable() ? SNAME("font_color") : SNAME("font_uneditable_color"));
|
||||
Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
|
||||
Color caret_color = get_theme_color(SNAME("caret_color"));
|
||||
Color selection_color = theme_cache.selection_color;
|
||||
Color font_color;
|
||||
if (is_editable()) {
|
||||
font_color = theme_cache.font_color;
|
||||
} else {
|
||||
font_color = theme_cache.font_uneditable_color;
|
||||
}
|
||||
Color font_selected_color = theme_cache.font_selected_color;
|
||||
Color caret_color = theme_cache.caret_color;
|
||||
|
||||
// Draw placeholder color.
|
||||
if (using_placeholder) {
|
||||
font_color = get_theme_color(SNAME("font_placeholder_color"));
|
||||
font_color = theme_cache.font_placeholder_color;
|
||||
}
|
||||
|
||||
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
|
||||
if (right_icon.is_valid() || display_clear_icon) {
|
||||
Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
|
||||
Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
|
||||
Color color_icon(1, 1, 1, !is_editable() ? .5 * .9 : .9);
|
||||
if (display_clear_icon) {
|
||||
if (clear_button_status.press_attempt && clear_button_status.pressing_inside) {
|
||||
color_icon = get_theme_color(SNAME("clear_button_color_pressed"));
|
||||
color_icon = theme_cache.clear_button_color_pressed;
|
||||
} else {
|
||||
color_icon = get_theme_color(SNAME("clear_button_color"));
|
||||
color_icon = theme_cache.clear_button_color;
|
||||
}
|
||||
}
|
||||
|
||||
@ -879,8 +911,8 @@ void LineEdit::_notification(int p_what) {
|
||||
|
||||
// Draw text.
|
||||
ofs.y += TS->shaped_text_get_ascent(text_rid);
|
||||
Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
int outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
Color font_outline_color = theme_cache.font_outline_color;
|
||||
int outline_size = theme_cache.font_outline_size;
|
||||
if (outline_size > 0 && font_outline_color.a > 0) {
|
||||
Vector2 oofs = ofs;
|
||||
for (int i = 0; i < gl_size; i++) {
|
||||
@ -918,7 +950,7 @@ void LineEdit::_notification(int p_what) {
|
||||
ofs.x = x_ofs + scroll_offset;
|
||||
if (draw_caret || drag_caret_force_displayed) {
|
||||
// Prevent carets from disappearing at theme scales below 1.0 (if the caret width is 1).
|
||||
const int caret_width = get_theme_constant(SNAME("caret_width")) * MAX(1, get_theme_default_base_scale());
|
||||
const int caret_width = theme_cache.caret_width * MAX(1, theme_cache.base_scale);
|
||||
|
||||
if (ime_text.length() == 0) {
|
||||
// Normal caret.
|
||||
@ -926,7 +958,7 @@ void LineEdit::_notification(int p_what) {
|
||||
|
||||
if (caret.l_caret == Rect2() && caret.t_caret == Rect2()) {
|
||||
// No carets, add one at the start.
|
||||
int h = get_theme_font(SNAME("font"))->get_height(get_theme_font_size(SNAME("font_size")));
|
||||
int h = theme_cache.font->get_height(theme_cache.font_size);
|
||||
int y = style->get_offset().y + (y_area - h) / 2;
|
||||
if (rtl) {
|
||||
caret.l_dir = TextServer::DIRECTION_RTL;
|
||||
@ -1193,7 +1225,7 @@ void LineEdit::shift_selection_check_post(bool p_shift) {
|
||||
}
|
||||
|
||||
void LineEdit::set_caret_at_pixel_pos(int p_x) {
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
Ref<StyleBox> style = theme_cache.normal;
|
||||
bool rtl = is_layout_rtl();
|
||||
|
||||
int x_ofs = 0;
|
||||
@ -1226,7 +1258,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) {
|
||||
bool using_placeholder = text.is_empty() && ime_text.is_empty();
|
||||
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
|
||||
if (right_icon.is_valid() || display_clear_icon) {
|
||||
Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
|
||||
Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
|
||||
if (alignment == HORIZONTAL_ALIGNMENT_CENTER) {
|
||||
if (Math::is_zero_approx(scroll_offset)) {
|
||||
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
|
||||
@ -1241,7 +1273,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) {
|
||||
}
|
||||
|
||||
Vector2 LineEdit::get_caret_pixel_pos() {
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
Ref<StyleBox> style = theme_cache.normal;
|
||||
bool rtl = is_layout_rtl();
|
||||
|
||||
int x_ofs = 0;
|
||||
@ -1274,7 +1306,7 @@ Vector2 LineEdit::get_caret_pixel_pos() {
|
||||
bool using_placeholder = text.is_empty() && ime_text.is_empty();
|
||||
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
|
||||
if (right_icon.is_valid() || display_clear_icon) {
|
||||
Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
|
||||
Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
|
||||
if (alignment == HORIZONTAL_ALIGNMENT_CENTER) {
|
||||
if (Math::is_zero_approx(scroll_offset)) {
|
||||
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
|
||||
@ -1559,7 +1591,7 @@ void LineEdit::set_caret_column(int p_column) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
Ref<StyleBox> style = theme_cache.normal;
|
||||
bool rtl = is_layout_rtl();
|
||||
|
||||
int x_ofs = 0;
|
||||
@ -1593,7 +1625,7 @@ void LineEdit::set_caret_column(int p_column) {
|
||||
bool using_placeholder = text.is_empty() && ime_text.is_empty();
|
||||
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
|
||||
if (right_icon.is_valid() || display_clear_icon) {
|
||||
Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
|
||||
Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
|
||||
if (alignment == HORIZONTAL_ALIGNMENT_CENTER) {
|
||||
if (Math::is_zero_approx(scroll_offset)) {
|
||||
x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2);
|
||||
@ -1664,15 +1696,15 @@ void LineEdit::clear_internal() {
|
||||
}
|
||||
|
||||
Size2 LineEdit::get_minimum_size() const {
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
Ref<Font> font = get_theme_font(SNAME("font"));
|
||||
int font_size = get_theme_font_size(SNAME("font_size"));
|
||||
Ref<StyleBox> style = theme_cache.normal;
|
||||
Ref<Font> font = theme_cache.font;
|
||||
int font_size = theme_cache.font_size;
|
||||
|
||||
Size2 min_size;
|
||||
|
||||
// Minimum size of text.
|
||||
float em_space_size = font->get_char_size('M', font_size).x;
|
||||
min_size.width = get_theme_constant(SNAME("minimum_character_width")) * em_space_size;
|
||||
min_size.width = theme_cache.minimum_character_width * em_space_size;
|
||||
|
||||
if (expand_to_text_length) {
|
||||
// Add a space because some fonts are too exact, and because caret needs a bit more when at the end.
|
||||
@ -1688,9 +1720,8 @@ Size2 LineEdit::get_minimum_size() const {
|
||||
icon_max_width = right_icon->get_width();
|
||||
}
|
||||
if (clear_button_enabled) {
|
||||
Ref<Texture2D> clear_icon = Control::get_theme_icon(SNAME("clear"));
|
||||
min_size.height = MAX(min_size.height, clear_icon->get_height());
|
||||
icon_max_width = MAX(icon_max_width, clear_icon->get_width());
|
||||
min_size.height = MAX(min_size.height, theme_cache.clear_icon->get_height());
|
||||
icon_max_width = MAX(icon_max_width, theme_cache.clear_icon->get_width());
|
||||
}
|
||||
min_size.width += icon_max_width;
|
||||
|
||||
@ -2155,8 +2186,8 @@ void LineEdit::_shape() {
|
||||
}
|
||||
TS->shaped_text_set_preserve_control(text_rid, draw_control_chars);
|
||||
|
||||
const Ref<Font> &font = get_theme_font(SNAME("font"));
|
||||
int font_size = get_theme_font_size(SNAME("font_size"));
|
||||
const Ref<Font> &font = theme_cache.font;
|
||||
int font_size = theme_cache.font_size;
|
||||
ERR_FAIL_COND(font.is_null());
|
||||
TS->shaped_text_add_string(text_rid, t, font->get_rids(), font_size, font->get_opentype_features(), language);
|
||||
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
|
||||
@ -2176,12 +2207,12 @@ void LineEdit::_shape() {
|
||||
|
||||
void LineEdit::_fit_to_width() {
|
||||
if (alignment == HORIZONTAL_ALIGNMENT_FILL) {
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
Ref<StyleBox> style = theme_cache.normal;
|
||||
int t_width = get_size().width - style->get_margin(SIDE_RIGHT) - style->get_margin(SIDE_LEFT);
|
||||
bool using_placeholder = text.is_empty() && ime_text.is_empty();
|
||||
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
|
||||
if (right_icon.is_valid() || display_clear_icon) {
|
||||
Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon;
|
||||
Ref<Texture2D> r_icon = display_clear_icon ? theme_cache.clear_icon : right_icon;
|
||||
t_width -= r_icon->get_width();
|
||||
}
|
||||
TS->shaped_text_fit_to_width(text_rid, MAX(t_width, full_width));
|
||||
|
@ -174,6 +174,31 @@ private:
|
||||
double caret_blink_timer = 0.0;
|
||||
bool caret_blinking = false;
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> normal;
|
||||
Ref<StyleBox> read_only;
|
||||
Ref<StyleBox> focus;
|
||||
|
||||
Ref<Font> font;
|
||||
int font_size = 0;
|
||||
Color font_color;
|
||||
Color font_uneditable_color;
|
||||
Color font_selected_color;
|
||||
int font_outline_size;
|
||||
Color font_outline_color;
|
||||
Color font_placeholder_color;
|
||||
int caret_width = 0;
|
||||
Color caret_color;
|
||||
int minimum_character_width = 0;
|
||||
Color selection_color;
|
||||
|
||||
Ref<Texture2D> clear_icon;
|
||||
Color clear_button_color;
|
||||
Color clear_button_color_pressed;
|
||||
|
||||
int base_scale = 0;
|
||||
} theme_cache;
|
||||
|
||||
bool _is_over_clear_button(const Point2 &p_pos) const;
|
||||
|
||||
void _clear_undo_stack();
|
||||
@ -215,6 +240,7 @@ private:
|
||||
void _ensure_menu();
|
||||
|
||||
protected:
|
||||
virtual void _update_theme_item_cache() override;
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
|
||||
|
@ -33,8 +33,8 @@
|
||||
#include "core/string/translation.h"
|
||||
|
||||
void LinkButton::_shape() {
|
||||
Ref<Font> font = get_theme_font(SNAME("font"));
|
||||
int font_size = get_theme_font_size(SNAME("font_size"));
|
||||
Ref<Font> font = theme_cache.font;
|
||||
int font_size = theme_cache.font_size;
|
||||
|
||||
text_buf->clear();
|
||||
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
|
||||
@ -125,6 +125,26 @@ Size2 LinkButton::get_minimum_size() const {
|
||||
return text_buf->get_size();
|
||||
}
|
||||
|
||||
void LinkButton::_update_theme_item_cache() {
|
||||
BaseButton::_update_theme_item_cache();
|
||||
|
||||
theme_cache.focus = get_theme_stylebox(SNAME("focus"));
|
||||
|
||||
theme_cache.font_color = get_theme_color(SNAME("font_color"));
|
||||
theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
|
||||
theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
|
||||
theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
|
||||
theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
|
||||
theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
|
||||
|
||||
theme_cache.font = get_theme_font(SNAME("font"));
|
||||
theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
|
||||
theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
|
||||
theme_cache.underline_spacing = get_theme_constant(SNAME("underline_spacing"));
|
||||
}
|
||||
|
||||
void LinkButton::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_TRANSLATION_CHANGED: {
|
||||
@ -153,9 +173,9 @@ void LinkButton::_notification(int p_what) {
|
||||
switch (get_draw_mode()) {
|
||||
case DRAW_NORMAL: {
|
||||
if (has_focus()) {
|
||||
color = get_theme_color(SNAME("font_focus_color"));
|
||||
color = theme_cache.font_focus_color;
|
||||
} else {
|
||||
color = get_theme_color(SNAME("font_color"));
|
||||
color = theme_cache.font_color;
|
||||
}
|
||||
|
||||
do_underline = underline_mode == UNDERLINE_MODE_ALWAYS;
|
||||
@ -163,35 +183,35 @@ void LinkButton::_notification(int p_what) {
|
||||
case DRAW_HOVER_PRESSED:
|
||||
case DRAW_PRESSED: {
|
||||
if (has_theme_color(SNAME("font_pressed_color"))) {
|
||||
color = get_theme_color(SNAME("font_pressed_color"));
|
||||
color = theme_cache.font_pressed_color;
|
||||
} else {
|
||||
color = get_theme_color(SNAME("font_color"));
|
||||
color = theme_cache.font_color;
|
||||
}
|
||||
|
||||
do_underline = underline_mode != UNDERLINE_MODE_NEVER;
|
||||
|
||||
} break;
|
||||
case DRAW_HOVER: {
|
||||
color = get_theme_color(SNAME("font_hover_color"));
|
||||
color = theme_cache.font_hover_color;
|
||||
do_underline = underline_mode != UNDERLINE_MODE_NEVER;
|
||||
|
||||
} break;
|
||||
case DRAW_DISABLED: {
|
||||
color = get_theme_color(SNAME("font_disabled_color"));
|
||||
color = theme_cache.font_disabled_color;
|
||||
do_underline = underline_mode == UNDERLINE_MODE_ALWAYS;
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
if (has_focus()) {
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("focus"));
|
||||
Ref<StyleBox> style = theme_cache.focus;
|
||||
style->draw(ci, Rect2(Point2(), size));
|
||||
}
|
||||
|
||||
int width = text_buf->get_line_width();
|
||||
|
||||
Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
int outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
Color font_outline_color = theme_cache.font_outline_color;
|
||||
int outline_size = theme_cache.outline_size;
|
||||
if (is_layout_rtl()) {
|
||||
if (outline_size > 0 && font_outline_color.a > 0) {
|
||||
text_buf->draw_outline(get_canvas_item(), Vector2(size.width - width, 0), outline_size, font_outline_color);
|
||||
@ -205,7 +225,7 @@ void LinkButton::_notification(int p_what) {
|
||||
}
|
||||
|
||||
if (do_underline) {
|
||||
int underline_spacing = get_theme_constant(SNAME("underline_spacing")) + text_buf->get_line_underline_position();
|
||||
int underline_spacing = theme_cache.underline_spacing + text_buf->get_line_underline_position();
|
||||
int y = text_buf->get_line_ascent() + underline_spacing;
|
||||
|
||||
if (is_layout_rtl()) {
|
||||
|
@ -55,10 +55,29 @@ private:
|
||||
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
|
||||
Array st_args;
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> focus;
|
||||
|
||||
Color font_color;
|
||||
Color font_focus_color;
|
||||
Color font_pressed_color;
|
||||
Color font_hover_color;
|
||||
Color font_hover_pressed_color;
|
||||
Color font_disabled_color;
|
||||
|
||||
Ref<Font> font;
|
||||
int font_size = 0;
|
||||
int outline_size = 0;
|
||||
Color font_outline_color;
|
||||
|
||||
int underline_spacing = 0;
|
||||
} theme_cache;
|
||||
|
||||
void _shape();
|
||||
|
||||
protected:
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual void _update_theme_item_cache() override;
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
|
@ -30,12 +30,16 @@
|
||||
|
||||
#include "margin_container.h"
|
||||
|
||||
Size2 MarginContainer::get_minimum_size() const {
|
||||
int margin_left = get_theme_constant(SNAME("margin_left"));
|
||||
int margin_top = get_theme_constant(SNAME("margin_top"));
|
||||
int margin_right = get_theme_constant(SNAME("margin_right"));
|
||||
int margin_bottom = get_theme_constant(SNAME("margin_bottom"));
|
||||
void MarginContainer::_update_theme_item_cache() {
|
||||
Container::_update_theme_item_cache();
|
||||
|
||||
theme_cache.margin_left = get_theme_constant(SNAME("margin_left"));
|
||||
theme_cache.margin_top = get_theme_constant(SNAME("margin_top"));
|
||||
theme_cache.margin_right = get_theme_constant(SNAME("margin_right"));
|
||||
theme_cache.margin_bottom = get_theme_constant(SNAME("margin_bottom"));
|
||||
}
|
||||
|
||||
Size2 MarginContainer::get_minimum_size() const {
|
||||
Size2 max;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
@ -59,8 +63,8 @@ Size2 MarginContainer::get_minimum_size() const {
|
||||
}
|
||||
}
|
||||
|
||||
max.width += (margin_left + margin_right);
|
||||
max.height += (margin_top + margin_bottom);
|
||||
max.width += (theme_cache.margin_left + theme_cache.margin_right);
|
||||
max.height += (theme_cache.margin_top + theme_cache.margin_bottom);
|
||||
|
||||
return max;
|
||||
}
|
||||
@ -86,11 +90,6 @@ Vector<int> MarginContainer::get_allowed_size_flags_vertical() const {
|
||||
void MarginContainer::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_SORT_CHILDREN: {
|
||||
int margin_left = get_theme_constant(SNAME("margin_left"));
|
||||
int margin_top = get_theme_constant(SNAME("margin_top"));
|
||||
int margin_right = get_theme_constant(SNAME("margin_right"));
|
||||
int margin_bottom = get_theme_constant(SNAME("margin_bottom"));
|
||||
|
||||
Size2 s = get_size();
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
@ -102,9 +101,9 @@ void MarginContainer::_notification(int p_what) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int w = s.width - margin_left - margin_right;
|
||||
int h = s.height - margin_top - margin_bottom;
|
||||
fit_child_in_rect(c, Rect2(margin_left, margin_top, w, h));
|
||||
int w = s.width - theme_cache.margin_left - theme_cache.margin_right;
|
||||
int h = s.height - theme_cache.margin_top - theme_cache.margin_bottom;
|
||||
fit_child_in_rect(c, Rect2(theme_cache.margin_left, theme_cache.margin_top, w, h));
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -36,7 +36,16 @@
|
||||
class MarginContainer : public Container {
|
||||
GDCLASS(MarginContainer, Container);
|
||||
|
||||
struct ThemeCache {
|
||||
int margin_left = 0;
|
||||
int margin_top = 0;
|
||||
int margin_right = 0;
|
||||
int margin_bottom = 0;
|
||||
} theme_cache;
|
||||
|
||||
protected:
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
|
@ -340,6 +340,35 @@ void MenuBar::_update_menu() {
|
||||
queue_redraw();
|
||||
}
|
||||
|
||||
void MenuBar::_update_theme_item_cache() {
|
||||
Control::_update_theme_item_cache();
|
||||
|
||||
theme_cache.normal = get_theme_stylebox(SNAME("normal"));
|
||||
theme_cache.normal_mirrored = get_theme_stylebox(SNAME("normal_mirrored"));
|
||||
theme_cache.disabled = get_theme_stylebox(SNAME("disabled"));
|
||||
theme_cache.disabled_mirrored = get_theme_stylebox(SNAME("disabled_mirrored"));
|
||||
theme_cache.pressed = get_theme_stylebox(SNAME("pressed"));
|
||||
theme_cache.pressed_mirrored = get_theme_stylebox(SNAME("pressed_mirrored"));
|
||||
theme_cache.hover = get_theme_stylebox(SNAME("hover"));
|
||||
theme_cache.hover_mirrored = get_theme_stylebox(SNAME("hover_mirrored"));
|
||||
theme_cache.hover_pressed = get_theme_stylebox(SNAME("hover_pressed"));
|
||||
theme_cache.hover_pressed_mirrored = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
|
||||
|
||||
theme_cache.font = get_theme_font(SNAME("font"));
|
||||
theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
|
||||
theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
|
||||
theme_cache.font_color = get_theme_color(SNAME("font_color"));
|
||||
theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
|
||||
theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
|
||||
theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
|
||||
theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
|
||||
theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
|
||||
|
||||
theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
|
||||
}
|
||||
|
||||
void MenuBar::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
@ -394,8 +423,7 @@ void MenuBar::_notification(int p_what) {
|
||||
}
|
||||
|
||||
int MenuBar::_get_index_at_point(const Point2 &p_point) const {
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
int hsep = get_theme_constant(SNAME("h_separation"));
|
||||
Ref<StyleBox> style = theme_cache.normal;
|
||||
int offset = 0;
|
||||
for (int i = 0; i < menu_cache.size(); i++) {
|
||||
if (menu_cache[i].hidden) {
|
||||
@ -407,7 +435,7 @@ int MenuBar::_get_index_at_point(const Point2 &p_point) const {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
offset += size.x + hsep;
|
||||
offset += size.x + theme_cache.h_separation;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -415,8 +443,7 @@ int MenuBar::_get_index_at_point(const Point2 &p_point) const {
|
||||
Rect2 MenuBar::_get_menu_item_rect(int p_index) const {
|
||||
ERR_FAIL_INDEX_V(p_index, menu_cache.size(), Rect2());
|
||||
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
int hsep = get_theme_constant(SNAME("h_separation"));
|
||||
Ref<StyleBox> style = theme_cache.normal;
|
||||
|
||||
int offset = 0;
|
||||
for (int i = 0; i < p_index; i++) {
|
||||
@ -424,7 +451,7 @@ Rect2 MenuBar::_get_menu_item_rect(int p_index) const {
|
||||
continue;
|
||||
}
|
||||
Size2 size = menu_cache[i].text_buf->get_size() + style->get_minimum_size();
|
||||
offset += size.x + hsep;
|
||||
offset += size.x + theme_cache.h_separation;
|
||||
}
|
||||
|
||||
return Rect2(Point2(offset, 0), menu_cache[p_index].text_buf->get_size() + style->get_minimum_size());
|
||||
@ -443,76 +470,76 @@ void MenuBar::_draw_menu_item(int p_index) {
|
||||
}
|
||||
|
||||
Color color;
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
Ref<StyleBox> style = theme_cache.normal;
|
||||
Rect2 item_rect = _get_menu_item_rect(p_index);
|
||||
|
||||
if (menu_cache[p_index].disabled) {
|
||||
if (rtl && has_theme_stylebox(SNAME("disabled_mirrored"))) {
|
||||
style = get_theme_stylebox(SNAME("disabled_mirrored"));
|
||||
style = theme_cache.disabled_mirrored;
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("disabled"));
|
||||
style = theme_cache.disabled;
|
||||
}
|
||||
if (!flat) {
|
||||
style->draw(ci, item_rect);
|
||||
}
|
||||
color = get_theme_color(SNAME("font_disabled_color"));
|
||||
color = theme_cache.font_disabled_color;
|
||||
} else if (hovered && pressed && has_theme_stylebox("hover_pressed")) {
|
||||
if (rtl && has_theme_stylebox(SNAME("hover_pressed_mirrored"))) {
|
||||
style = get_theme_stylebox(SNAME("hover_pressed_mirrored"));
|
||||
style = theme_cache.hover_pressed_mirrored;
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("hover_pressed"));
|
||||
style = theme_cache.hover_pressed;
|
||||
}
|
||||
if (!flat) {
|
||||
style->draw(ci, item_rect);
|
||||
}
|
||||
if (has_theme_color(SNAME("font_hover_pressed_color"))) {
|
||||
color = get_theme_color(SNAME("font_hover_pressed_color"));
|
||||
color = theme_cache.font_hover_pressed_color;
|
||||
}
|
||||
} else if (pressed) {
|
||||
if (rtl && has_theme_stylebox(SNAME("pressed_mirrored"))) {
|
||||
style = get_theme_stylebox(SNAME("pressed_mirrored"));
|
||||
style = theme_cache.pressed_mirrored;
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("pressed"));
|
||||
style = theme_cache.pressed;
|
||||
}
|
||||
if (!flat) {
|
||||
style->draw(ci, item_rect);
|
||||
}
|
||||
if (has_theme_color(SNAME("font_pressed_color"))) {
|
||||
color = get_theme_color(SNAME("font_pressed_color"));
|
||||
color = theme_cache.font_pressed_color;
|
||||
} else {
|
||||
color = get_theme_color(SNAME("font_color"));
|
||||
color = theme_cache.font_color;
|
||||
}
|
||||
} else if (hovered) {
|
||||
if (rtl && has_theme_stylebox(SNAME("hover_mirrored"))) {
|
||||
style = get_theme_stylebox(SNAME("hover_mirrored"));
|
||||
style = theme_cache.hover_mirrored;
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("hover"));
|
||||
style = theme_cache.hover;
|
||||
}
|
||||
if (!flat) {
|
||||
style->draw(ci, item_rect);
|
||||
}
|
||||
color = get_theme_color(SNAME("font_hover_color"));
|
||||
color = theme_cache.font_hover_color;
|
||||
} else {
|
||||
if (rtl && has_theme_stylebox(SNAME("normal_mirrored"))) {
|
||||
style = get_theme_stylebox(SNAME("normal_mirrored"));
|
||||
style = theme_cache.normal_mirrored;
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("normal"));
|
||||
style = theme_cache.normal;
|
||||
}
|
||||
if (!flat) {
|
||||
style->draw(ci, item_rect);
|
||||
}
|
||||
// Focus colors only take precedence over normal state.
|
||||
if (has_focus()) {
|
||||
color = get_theme_color(SNAME("font_focus_color"));
|
||||
color = theme_cache.font_focus_color;
|
||||
} else {
|
||||
color = get_theme_color(SNAME("font_color"));
|
||||
color = theme_cache.font_color;
|
||||
}
|
||||
}
|
||||
|
||||
Point2 text_ofs = item_rect.position + Point2(style->get_margin(SIDE_LEFT), style->get_margin(SIDE_TOP));
|
||||
|
||||
Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
int outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
Color font_outline_color = theme_cache.font_outline_color;
|
||||
int outline_size = theme_cache.outline_size;
|
||||
if (outline_size > 0 && font_outline_color.a > 0) {
|
||||
menu_cache[p_index].text_buf->draw_outline(ci, text_ofs, outline_size, font_outline_color);
|
||||
}
|
||||
@ -520,16 +547,13 @@ void MenuBar::_draw_menu_item(int p_index) {
|
||||
}
|
||||
|
||||
void MenuBar::shape(Menu &p_menu) {
|
||||
Ref<Font> font = get_theme_font(SNAME("font"));
|
||||
int font_size = get_theme_font_size(SNAME("font_size"));
|
||||
|
||||
p_menu.text_buf->clear();
|
||||
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
|
||||
p_menu.text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
|
||||
} else {
|
||||
p_menu.text_buf->set_direction((TextServer::Direction)text_direction);
|
||||
}
|
||||
p_menu.text_buf->add_string(p_menu.name, font, font_size, language);
|
||||
p_menu.text_buf->add_string(p_menu.name, theme_cache.font, theme_cache.font_size, language);
|
||||
}
|
||||
|
||||
void MenuBar::_refresh_menu_names() {
|
||||
@ -759,7 +783,7 @@ Size2 MenuBar::get_minimum_size() const {
|
||||
return Size2();
|
||||
}
|
||||
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
|
||||
Ref<StyleBox> style = theme_cache.normal;
|
||||
|
||||
Vector2 size;
|
||||
for (int i = 0; i < menu_cache.size(); i++) {
|
||||
@ -771,7 +795,7 @@ Size2 MenuBar::get_minimum_size() const {
|
||||
size.x += sz.x;
|
||||
}
|
||||
if (menu_cache.size() > 1) {
|
||||
size.x += get_theme_constant(SNAME("h_separation")) * (menu_cache.size() - 1);
|
||||
size.x += theme_cache.h_separation * (menu_cache.size() - 1);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
@ -76,6 +76,33 @@ class MenuBar : public Control {
|
||||
Vector2i old_mouse_pos;
|
||||
ObjectID shortcut_context;
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> normal;
|
||||
Ref<StyleBox> normal_mirrored;
|
||||
Ref<StyleBox> disabled;
|
||||
Ref<StyleBox> disabled_mirrored;
|
||||
Ref<StyleBox> pressed;
|
||||
Ref<StyleBox> pressed_mirrored;
|
||||
Ref<StyleBox> hover;
|
||||
Ref<StyleBox> hover_mirrored;
|
||||
Ref<StyleBox> hover_pressed;
|
||||
Ref<StyleBox> hover_pressed_mirrored;
|
||||
|
||||
Ref<Font> font;
|
||||
int font_size = 0;
|
||||
int outline_size = 0;
|
||||
Color font_outline_color;
|
||||
|
||||
Color font_color;
|
||||
Color font_disabled_color;
|
||||
Color font_pressed_color;
|
||||
Color font_hover_color;
|
||||
Color font_hover_pressed_color;
|
||||
Color font_focus_color;
|
||||
|
||||
int h_separation = 0;
|
||||
} theme_cache;
|
||||
|
||||
int _get_index_at_point(const Point2 &p_point) const;
|
||||
Rect2 _get_menu_item_rect(int p_index) const;
|
||||
void _draw_menu_item(int p_index);
|
||||
@ -96,6 +123,7 @@ class MenuBar : public Control {
|
||||
protected:
|
||||
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
|
||||
|
||||
virtual void _update_theme_item_cache() override;
|
||||
void _notification(int p_what);
|
||||
virtual void add_child_notify(Node *p_child) override;
|
||||
virtual void move_child_notify(Node *p_child) override;
|
||||
|
@ -43,11 +43,11 @@ Size2 OptionButton::get_minimum_size() const {
|
||||
}
|
||||
|
||||
if (has_theme_icon(SNAME("arrow"))) {
|
||||
const Size2 padding = get_theme_stylebox(SNAME("normal"))->get_minimum_size();
|
||||
const Size2 arrow_size = Control::get_theme_icon(SNAME("arrow"))->get_size();
|
||||
const Size2 padding = theme_cache.normal->get_minimum_size();
|
||||
const Size2 arrow_size = theme_cache.arrow_icon->get_size();
|
||||
|
||||
Size2 content_size = minsize - padding;
|
||||
content_size.width += arrow_size.width + MAX(0, get_theme_constant(SNAME("h_separation")));
|
||||
content_size.width += arrow_size.width + MAX(0, theme_cache.h_separation);
|
||||
content_size.height = MAX(content_size.height, arrow_size.height);
|
||||
|
||||
minsize = content_size + padding;
|
||||
@ -56,35 +56,63 @@ Size2 OptionButton::get_minimum_size() const {
|
||||
return minsize;
|
||||
}
|
||||
|
||||
void OptionButton::_update_theme_item_cache() {
|
||||
Button::_update_theme_item_cache();
|
||||
|
||||
theme_cache.normal = get_theme_stylebox(SNAME("normal"));
|
||||
|
||||
theme_cache.font_color = get_theme_color(SNAME("font_color"));
|
||||
theme_cache.font_focus_color = get_theme_color(SNAME("font_focus_color"));
|
||||
theme_cache.font_pressed_color = get_theme_color(SNAME("font_pressed_color"));
|
||||
theme_cache.font_hover_color = get_theme_color(SNAME("font_hover_color"));
|
||||
theme_cache.font_hover_pressed_color = get_theme_color(SNAME("font_hover_pressed_color"));
|
||||
theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
|
||||
|
||||
theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
|
||||
|
||||
theme_cache.arrow_icon = get_theme_icon(SNAME("arrow"));
|
||||
theme_cache.arrow_margin = get_theme_constant(SNAME("arrow_margin"));
|
||||
theme_cache.modulate_arrow = get_theme_constant(SNAME("modulate_arrow"));
|
||||
}
|
||||
|
||||
void OptionButton::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_POSTINITIALIZE: {
|
||||
if (has_theme_icon(SNAME("arrow"))) {
|
||||
if (is_layout_rtl()) {
|
||||
_set_internal_margin(SIDE_LEFT, theme_cache.arrow_icon->get_width());
|
||||
} else {
|
||||
_set_internal_margin(SIDE_RIGHT, theme_cache.arrow_icon->get_width());
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_DRAW: {
|
||||
if (!has_theme_icon(SNAME("arrow"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
RID ci = get_canvas_item();
|
||||
Ref<Texture2D> arrow = Control::get_theme_icon(SNAME("arrow"));
|
||||
Color clr = Color(1, 1, 1);
|
||||
if (get_theme_constant(SNAME("modulate_arrow"))) {
|
||||
if (theme_cache.modulate_arrow) {
|
||||
switch (get_draw_mode()) {
|
||||
case DRAW_PRESSED:
|
||||
clr = get_theme_color(SNAME("font_pressed_color"));
|
||||
clr = theme_cache.font_pressed_color;
|
||||
break;
|
||||
case DRAW_HOVER:
|
||||
clr = get_theme_color(SNAME("font_hover_color"));
|
||||
clr = theme_cache.font_hover_color;
|
||||
break;
|
||||
case DRAW_HOVER_PRESSED:
|
||||
clr = get_theme_color(SNAME("font_hover_pressed_color"));
|
||||
clr = theme_cache.font_hover_pressed_color;
|
||||
break;
|
||||
case DRAW_DISABLED:
|
||||
clr = get_theme_color(SNAME("font_disabled_color"));
|
||||
clr = theme_cache.font_disabled_color;
|
||||
break;
|
||||
default:
|
||||
if (has_focus()) {
|
||||
clr = get_theme_color(SNAME("font_focus_color"));
|
||||
clr = theme_cache.font_focus_color;
|
||||
} else {
|
||||
clr = get_theme_color(SNAME("font_color"));
|
||||
clr = theme_cache.font_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,11 +121,11 @@ void OptionButton::_notification(int p_what) {
|
||||
|
||||
Point2 ofs;
|
||||
if (is_layout_rtl()) {
|
||||
ofs = Point2(get_theme_constant(SNAME("arrow_margin")), int(Math::abs((size.height - arrow->get_height()) / 2)));
|
||||
ofs = Point2(theme_cache.arrow_margin, int(Math::abs((size.height - theme_cache.arrow_icon->get_height()) / 2)));
|
||||
} else {
|
||||
ofs = Point2(size.width - arrow->get_width() - get_theme_constant(SNAME("arrow_margin")), int(Math::abs((size.height - arrow->get_height()) / 2)));
|
||||
ofs = Point2(size.width - theme_cache.arrow_icon->get_width() - theme_cache.arrow_margin, int(Math::abs((size.height - theme_cache.arrow_icon->get_height()) / 2)));
|
||||
}
|
||||
arrow->draw(ci, ofs, clr);
|
||||
theme_cache.arrow_icon->draw(ci, ofs, clr);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_TRANSLATION_CHANGED:
|
||||
@ -108,11 +136,11 @@ void OptionButton::_notification(int p_what) {
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
if (has_theme_icon(SNAME("arrow"))) {
|
||||
if (is_layout_rtl()) {
|
||||
_set_internal_margin(SIDE_LEFT, Control::get_theme_icon(SNAME("arrow"))->get_width());
|
||||
_set_internal_margin(SIDE_LEFT, theme_cache.arrow_icon->get_width());
|
||||
_set_internal_margin(SIDE_RIGHT, 0.f);
|
||||
} else {
|
||||
_set_internal_margin(SIDE_LEFT, 0.f);
|
||||
_set_internal_margin(SIDE_RIGHT, Control::get_theme_icon(SNAME("arrow"))->get_width());
|
||||
_set_internal_margin(SIDE_RIGHT, theme_cache.arrow_icon->get_width());
|
||||
}
|
||||
}
|
||||
_refresh_size_cache();
|
||||
@ -540,15 +568,6 @@ OptionButton::OptionButton(const String &p_text) :
|
||||
Button(p_text) {
|
||||
set_toggle_mode(true);
|
||||
set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT);
|
||||
if (is_layout_rtl()) {
|
||||
if (has_theme_icon(SNAME("arrow"))) {
|
||||
_set_internal_margin(SIDE_LEFT, Control::get_theme_icon(SNAME("arrow"))->get_width());
|
||||
}
|
||||
} else {
|
||||
if (has_theme_icon(SNAME("arrow"))) {
|
||||
_set_internal_margin(SIDE_RIGHT, Control::get_theme_icon(SNAME("arrow"))->get_width());
|
||||
}
|
||||
}
|
||||
set_action_mode(ACTION_MODE_BUTTON_PRESS);
|
||||
|
||||
popup = memnew(PopupMenu);
|
||||
|
@ -43,6 +43,23 @@ class OptionButton : public Button {
|
||||
Vector2 _cached_size;
|
||||
bool cache_refresh_pending = false;
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> normal;
|
||||
|
||||
Color font_color;
|
||||
Color font_focus_color;
|
||||
Color font_pressed_color;
|
||||
Color font_hover_color;
|
||||
Color font_hover_pressed_color;
|
||||
Color font_disabled_color;
|
||||
|
||||
int h_separation = 0;
|
||||
|
||||
Ref<Texture2D> arrow_icon;
|
||||
int arrow_margin = 0;
|
||||
int modulate_arrow = 0;
|
||||
} theme_cache;
|
||||
|
||||
void _focused(int p_which);
|
||||
void _selected(int p_which);
|
||||
void _select(int p_which, bool p_emit = false);
|
||||
@ -54,6 +71,7 @@ class OptionButton : public Button {
|
||||
|
||||
protected:
|
||||
Size2 get_minimum_size() const override;
|
||||
virtual void _update_theme_item_cache() override;
|
||||
void _notification(int p_what);
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
|
@ -30,12 +30,17 @@
|
||||
|
||||
#include "panel.h"
|
||||
|
||||
void Panel::_update_theme_item_cache() {
|
||||
Control::_update_theme_item_cache();
|
||||
|
||||
theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
|
||||
}
|
||||
|
||||
void Panel::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
RID ci = get_canvas_item();
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
|
||||
style->draw(ci, Rect2(Point2(), get_size()));
|
||||
theme_cache.panel_style->draw(ci, Rect2(Point2(), get_size()));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,13 @@
|
||||
class Panel : public Control {
|
||||
GDCLASS(Panel, Control);
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> panel_style;
|
||||
} theme_cache;
|
||||
|
||||
protected:
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
|
@ -31,14 +31,6 @@
|
||||
#include "panel_container.h"
|
||||
|
||||
Size2 PanelContainer::get_minimum_size() const {
|
||||
Ref<StyleBox> style;
|
||||
|
||||
if (has_theme_stylebox(SNAME("panel"))) {
|
||||
style = get_theme_stylebox(SNAME("panel"));
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
|
||||
}
|
||||
|
||||
Size2 ms;
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *c = Object::cast_to<Control>(get_child(i));
|
||||
@ -54,8 +46,8 @@ Size2 PanelContainer::get_minimum_size() const {
|
||||
ms.height = MAX(ms.height, minsize.height);
|
||||
}
|
||||
|
||||
if (style.is_valid()) {
|
||||
ms += style->get_minimum_size();
|
||||
if (theme_cache.panel_style.is_valid()) {
|
||||
ms += theme_cache.panel_style->get_minimum_size();
|
||||
}
|
||||
return ms;
|
||||
}
|
||||
@ -78,35 +70,25 @@ Vector<int> PanelContainer::get_allowed_size_flags_vertical() const {
|
||||
return flags;
|
||||
}
|
||||
|
||||
void PanelContainer::_update_theme_item_cache() {
|
||||
Container::_update_theme_item_cache();
|
||||
|
||||
theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
|
||||
}
|
||||
|
||||
void PanelContainer::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
RID ci = get_canvas_item();
|
||||
Ref<StyleBox> style;
|
||||
|
||||
if (has_theme_stylebox(SNAME("panel"))) {
|
||||
style = get_theme_stylebox(SNAME("panel"));
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
|
||||
}
|
||||
|
||||
style->draw(ci, Rect2(Point2(), get_size()));
|
||||
theme_cache.panel_style->draw(ci, Rect2(Point2(), get_size()));
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_SORT_CHILDREN: {
|
||||
Ref<StyleBox> style;
|
||||
|
||||
if (has_theme_stylebox(SNAME("panel"))) {
|
||||
style = get_theme_stylebox(SNAME("panel"));
|
||||
} else {
|
||||
style = get_theme_stylebox(SNAME("panel"), SNAME("PanelContainer"));
|
||||
}
|
||||
|
||||
Size2 size = get_size();
|
||||
Point2 ofs;
|
||||
if (style.is_valid()) {
|
||||
size -= style->get_minimum_size();
|
||||
ofs += style->get_offset();
|
||||
if (theme_cache.panel_style.is_valid()) {
|
||||
size -= theme_cache.panel_style->get_minimum_size();
|
||||
ofs += theme_cache.panel_style->get_offset();
|
||||
}
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
|
@ -36,7 +36,12 @@
|
||||
class PanelContainer : public Container {
|
||||
GDCLASS(PanelContainer, Container);
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> panel_style;
|
||||
} theme_cache;
|
||||
|
||||
protected:
|
||||
virtual void _update_theme_item_cache() override;
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
|
@ -33,18 +33,13 @@
|
||||
#include "scene/resources/text_line.h"
|
||||
|
||||
Size2 ProgressBar::get_minimum_size() const {
|
||||
Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
|
||||
Ref<StyleBox> fg = get_theme_stylebox(SNAME("fg"));
|
||||
Ref<Font> font = get_theme_font(SNAME("font"));
|
||||
int font_size = get_theme_font_size(SNAME("font_size"));
|
||||
|
||||
Size2 minimum_size = bg->get_minimum_size();
|
||||
minimum_size.height = MAX(minimum_size.height, fg->get_minimum_size().height);
|
||||
minimum_size.width = MAX(minimum_size.width, fg->get_minimum_size().width);
|
||||
Size2 minimum_size = theme_cache.bg_style->get_minimum_size();
|
||||
minimum_size.height = MAX(minimum_size.height, theme_cache.fg_style->get_minimum_size().height);
|
||||
minimum_size.width = MAX(minimum_size.width, theme_cache.fg_style->get_minimum_size().width);
|
||||
if (percent_visible) {
|
||||
String txt = "100%";
|
||||
TextLine tl = TextLine(txt, font, font_size);
|
||||
minimum_size.height = MAX(minimum_size.height, bg->get_minimum_size().height + tl.get_size().y);
|
||||
TextLine tl = TextLine(txt, theme_cache.font, theme_cache.font_size);
|
||||
minimum_size.height = MAX(minimum_size.height, theme_cache.bg_style->get_minimum_size().height + tl.get_size().y);
|
||||
} else { // this is needed, else the progressbar will collapse
|
||||
minimum_size.width = MAX(minimum_size.width, 1);
|
||||
minimum_size.height = MAX(minimum_size.height, 1);
|
||||
@ -52,23 +47,30 @@ Size2 ProgressBar::get_minimum_size() const {
|
||||
return minimum_size;
|
||||
}
|
||||
|
||||
void ProgressBar::_update_theme_item_cache() {
|
||||
Range::_update_theme_item_cache();
|
||||
|
||||
theme_cache.bg_style = get_theme_stylebox(SNAME("bg"));
|
||||
theme_cache.fg_style = get_theme_stylebox(SNAME("fg"));
|
||||
|
||||
theme_cache.font = get_theme_font(SNAME("font"));
|
||||
theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
|
||||
theme_cache.font_color = get_theme_color(SNAME("font_color"));
|
||||
theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
}
|
||||
|
||||
void ProgressBar::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"));
|
||||
Ref<StyleBox> fg = get_theme_stylebox(SNAME("fg"));
|
||||
Ref<Font> font = get_theme_font(SNAME("font"));
|
||||
int font_size = get_theme_font_size(SNAME("font_size"));
|
||||
Color font_color = get_theme_color(SNAME("font_color"));
|
||||
|
||||
draw_style_box(bg, Rect2(Point2(), get_size()));
|
||||
draw_style_box(theme_cache.bg_style, Rect2(Point2(), get_size()));
|
||||
|
||||
float r = get_as_ratio();
|
||||
|
||||
switch (mode) {
|
||||
case FILL_BEGIN_TO_END:
|
||||
case FILL_END_TO_BEGIN: {
|
||||
int mp = fg->get_minimum_size().width;
|
||||
int mp = theme_cache.fg_style->get_minimum_size().width;
|
||||
int p = round(r * (get_size().width - mp));
|
||||
// We want FILL_BEGIN_TO_END to map to right to left when UI layout is RTL,
|
||||
// and left to right otherwise. And likewise for FILL_END_TO_BEGIN.
|
||||
@ -76,23 +78,23 @@ void ProgressBar::_notification(int p_what) {
|
||||
if (p > 0) {
|
||||
if (right_to_left) {
|
||||
int p_remaining = round((1.0 - r) * (get_size().width - mp));
|
||||
draw_style_box(fg, Rect2(Point2(p_remaining, 0), Size2(p + fg->get_minimum_size().width, get_size().height)));
|
||||
draw_style_box(theme_cache.fg_style, Rect2(Point2(p_remaining, 0), Size2(p + theme_cache.fg_style->get_minimum_size().width, get_size().height)));
|
||||
} else {
|
||||
draw_style_box(fg, Rect2(Point2(0, 0), Size2(p + fg->get_minimum_size().width, get_size().height)));
|
||||
draw_style_box(theme_cache.fg_style, Rect2(Point2(0, 0), Size2(p + theme_cache.fg_style->get_minimum_size().width, get_size().height)));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case FILL_TOP_TO_BOTTOM:
|
||||
case FILL_BOTTOM_TO_TOP: {
|
||||
int mp = fg->get_minimum_size().height;
|
||||
int mp = theme_cache.fg_style->get_minimum_size().height;
|
||||
int p = round(r * (get_size().height - mp));
|
||||
|
||||
if (p > 0) {
|
||||
if (mode == FILL_TOP_TO_BOTTOM) {
|
||||
draw_style_box(fg, Rect2(Point2(0, 0), Size2(get_size().width, p + fg->get_minimum_size().height)));
|
||||
draw_style_box(theme_cache.fg_style, Rect2(Point2(0, 0), Size2(get_size().width, p + theme_cache.fg_style->get_minimum_size().height)));
|
||||
} else {
|
||||
int p_remaining = round((1.0 - r) * (get_size().height - mp));
|
||||
draw_style_box(fg, Rect2(Point2(0, p_remaining), Size2(get_size().width, p + fg->get_minimum_size().height)));
|
||||
draw_style_box(theme_cache.fg_style, Rect2(Point2(0, p_remaining), Size2(get_size().width, p + theme_cache.fg_style->get_minimum_size().height)));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@ -102,14 +104,14 @@ void ProgressBar::_notification(int p_what) {
|
||||
|
||||
if (percent_visible) {
|
||||
String txt = TS->format_number(itos(int(get_as_ratio() * 100))) + TS->percent_sign();
|
||||
TextLine tl = TextLine(txt, font, font_size);
|
||||
TextLine tl = TextLine(txt, theme_cache.font, theme_cache.font_size);
|
||||
Vector2 text_pos = (Point2(get_size().width - tl.get_size().x, get_size().height - tl.get_size().y) / 2).round();
|
||||
Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
int outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
if (outline_size > 0 && font_outline_color.a > 0) {
|
||||
tl.draw_outline(get_canvas_item(), text_pos, outline_size, font_outline_color);
|
||||
|
||||
if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) {
|
||||
tl.draw_outline(get_canvas_item(), text_pos, theme_cache.font_outline_size, theme_cache.font_outline_color);
|
||||
}
|
||||
tl.draw(get_canvas_item(), text_pos, font_color);
|
||||
|
||||
tl.draw(get_canvas_item(), text_pos, theme_cache.font_color);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -38,7 +38,20 @@ class ProgressBar : public Range {
|
||||
|
||||
bool percent_visible = true;
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> bg_style;
|
||||
Ref<StyleBox> fg_style;
|
||||
|
||||
Ref<Font> font;
|
||||
int font_size = 0;
|
||||
Color font_color;
|
||||
int font_outline_size = 0;
|
||||
Color font_outline_color;
|
||||
} theme_cache;
|
||||
|
||||
protected:
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
|
@ -70,8 +70,8 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
if (b->is_pressed()) {
|
||||
double ofs = orientation == VERTICAL ? b->get_position().y : b->get_position().x;
|
||||
Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
|
||||
Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
|
||||
Ref<Texture2D> decr = theme_cache.decrement_icon;
|
||||
Ref<Texture2D> incr = theme_cache.increment_icon;
|
||||
|
||||
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
|
||||
double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width();
|
||||
@ -146,7 +146,7 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
if (drag.active) {
|
||||
double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x;
|
||||
Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
|
||||
Ref<Texture2D> decr = theme_cache.decrement_icon;
|
||||
|
||||
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
|
||||
ofs -= decr_size;
|
||||
@ -156,8 +156,8 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
|
||||
set_as_ratio(drag.value_at_click + diff);
|
||||
} else {
|
||||
double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x;
|
||||
Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
|
||||
Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
|
||||
Ref<Texture2D> decr = theme_cache.decrement_icon;
|
||||
Ref<Texture2D> incr = theme_cache.increment_icon;
|
||||
|
||||
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
|
||||
double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width();
|
||||
@ -217,6 +217,24 @@ void ScrollBar::gui_input(const Ref<InputEvent> &p_event) {
|
||||
}
|
||||
}
|
||||
|
||||
void ScrollBar::_update_theme_item_cache() {
|
||||
Range::_update_theme_item_cache();
|
||||
|
||||
theme_cache.scroll_style = get_theme_stylebox(SNAME("scroll"));
|
||||
theme_cache.scroll_focus_style = get_theme_stylebox(SNAME("scroll_focus"));
|
||||
theme_cache.scroll_offset_style = get_theme_stylebox(SNAME("hscroll"));
|
||||
theme_cache.grabber_style = get_theme_stylebox(SNAME("grabber"));
|
||||
theme_cache.grabber_hl_style = get_theme_stylebox(SNAME("grabber_highlight"));
|
||||
theme_cache.grabber_pressed_style = get_theme_stylebox(SNAME("grabber_pressed"));
|
||||
|
||||
theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
|
||||
theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
|
||||
theme_cache.increment_pressed_icon = get_theme_icon(SNAME("increment_pressed"));
|
||||
theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
|
||||
theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
|
||||
theme_cache.decrement_pressed_icon = get_theme_icon(SNAME("decrement_pressed"));
|
||||
}
|
||||
|
||||
void ScrollBar::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
@ -225,30 +243,30 @@ void ScrollBar::_notification(int p_what) {
|
||||
Ref<Texture2D> decr, incr;
|
||||
|
||||
if (decr_active) {
|
||||
decr = get_theme_icon(SNAME("decrement_pressed"));
|
||||
decr = theme_cache.decrement_pressed_icon;
|
||||
} else if (highlight == HIGHLIGHT_DECR) {
|
||||
decr = get_theme_icon(SNAME("decrement_highlight"));
|
||||
decr = theme_cache.decrement_hl_icon;
|
||||
} else {
|
||||
decr = get_theme_icon(SNAME("decrement"));
|
||||
decr = theme_cache.decrement_icon;
|
||||
}
|
||||
|
||||
if (incr_active) {
|
||||
incr = get_theme_icon(SNAME("increment_pressed"));
|
||||
incr = theme_cache.increment_pressed_icon;
|
||||
} else if (highlight == HIGHLIGHT_INCR) {
|
||||
incr = get_theme_icon(SNAME("increment_highlight"));
|
||||
incr = theme_cache.increment_hl_icon;
|
||||
} else {
|
||||
incr = get_theme_icon(SNAME("increment"));
|
||||
incr = theme_cache.increment_icon;
|
||||
}
|
||||
|
||||
Ref<StyleBox> bg = has_focus() ? get_theme_stylebox(SNAME("scroll_focus")) : get_theme_stylebox(SNAME("scroll"));
|
||||
Ref<StyleBox> bg = has_focus() ? theme_cache.scroll_focus_style : theme_cache.scroll_style;
|
||||
|
||||
Ref<StyleBox> grabber;
|
||||
if (drag.active) {
|
||||
grabber = get_theme_stylebox(SNAME("grabber_pressed"));
|
||||
grabber = theme_cache.grabber_pressed_style;
|
||||
} else if (highlight == HIGHLIGHT_RANGE) {
|
||||
grabber = get_theme_stylebox(SNAME("grabber_highlight"));
|
||||
grabber = theme_cache.grabber_hl_style;
|
||||
} else {
|
||||
grabber = get_theme_stylebox(SNAME("grabber"));
|
||||
grabber = theme_cache.grabber_style;
|
||||
}
|
||||
|
||||
Point2 ofs;
|
||||
@ -414,7 +432,7 @@ void ScrollBar::_notification(int p_what) {
|
||||
}
|
||||
|
||||
double ScrollBar::get_grabber_min_size() const {
|
||||
Ref<StyleBox> grabber = get_theme_stylebox(SNAME("grabber"));
|
||||
Ref<StyleBox> grabber = theme_cache.grabber_style;
|
||||
Size2 gminsize = grabber->get_minimum_size() + grabber->get_center_size();
|
||||
return (orientation == VERTICAL) ? gminsize.height : gminsize.width;
|
||||
}
|
||||
@ -435,17 +453,17 @@ double ScrollBar::get_area_size() const {
|
||||
switch (orientation) {
|
||||
case VERTICAL: {
|
||||
double area = get_size().height;
|
||||
area -= get_theme_stylebox(SNAME("scroll"))->get_minimum_size().height;
|
||||
area -= get_theme_icon(SNAME("increment"))->get_height();
|
||||
area -= get_theme_icon(SNAME("decrement"))->get_height();
|
||||
area -= theme_cache.scroll_style->get_minimum_size().height;
|
||||
area -= theme_cache.increment_icon->get_height();
|
||||
area -= theme_cache.decrement_icon->get_height();
|
||||
area -= get_grabber_min_size();
|
||||
return area;
|
||||
} break;
|
||||
case HORIZONTAL: {
|
||||
double area = get_size().width;
|
||||
area -= get_theme_stylebox(SNAME("scroll"))->get_minimum_size().width;
|
||||
area -= get_theme_icon(SNAME("increment"))->get_width();
|
||||
area -= get_theme_icon(SNAME("decrement"))->get_width();
|
||||
area -= theme_cache.scroll_style->get_minimum_size().width;
|
||||
area -= theme_cache.increment_icon->get_width();
|
||||
area -= theme_cache.decrement_icon->get_width();
|
||||
area -= get_grabber_min_size();
|
||||
return area;
|
||||
} break;
|
||||
@ -459,13 +477,13 @@ double ScrollBar::get_area_offset() const {
|
||||
double ofs = 0.0;
|
||||
|
||||
if (orientation == VERTICAL) {
|
||||
ofs += get_theme_stylebox(SNAME("hscroll"))->get_margin(SIDE_TOP);
|
||||
ofs += get_theme_icon(SNAME("decrement"))->get_height();
|
||||
ofs += theme_cache.scroll_offset_style->get_margin(SIDE_TOP);
|
||||
ofs += theme_cache.decrement_icon->get_height();
|
||||
}
|
||||
|
||||
if (orientation == HORIZONTAL) {
|
||||
ofs += get_theme_stylebox(SNAME("hscroll"))->get_margin(SIDE_LEFT);
|
||||
ofs += get_theme_icon(SNAME("decrement"))->get_width();
|
||||
ofs += theme_cache.scroll_offset_style->get_margin(SIDE_LEFT);
|
||||
ofs += theme_cache.decrement_icon->get_width();
|
||||
}
|
||||
|
||||
return ofs;
|
||||
@ -476,9 +494,9 @@ double ScrollBar::get_grabber_offset() const {
|
||||
}
|
||||
|
||||
Size2 ScrollBar::get_minimum_size() const {
|
||||
Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
|
||||
Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
|
||||
Ref<StyleBox> bg = get_theme_stylebox(SNAME("scroll"));
|
||||
Ref<Texture2D> incr = theme_cache.increment_icon;
|
||||
Ref<Texture2D> decr = theme_cache.decrement_icon;
|
||||
Ref<StyleBox> bg = theme_cache.scroll_style;
|
||||
Size2 minsize;
|
||||
|
||||
if (orientation == VERTICAL) {
|
||||
|
@ -86,14 +86,31 @@ class ScrollBar : public Range {
|
||||
double target_scroll = 0.0;
|
||||
bool smooth_scroll_enabled = false;
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> scroll_style;
|
||||
Ref<StyleBox> scroll_focus_style;
|
||||
Ref<StyleBox> scroll_offset_style;
|
||||
Ref<StyleBox> grabber_style;
|
||||
Ref<StyleBox> grabber_hl_style;
|
||||
Ref<StyleBox> grabber_pressed_style;
|
||||
|
||||
Ref<Texture2D> increment_icon;
|
||||
Ref<Texture2D> increment_hl_icon;
|
||||
Ref<Texture2D> increment_pressed_icon;
|
||||
Ref<Texture2D> decrement_icon;
|
||||
Ref<Texture2D> decrement_hl_icon;
|
||||
Ref<Texture2D> decrement_pressed_icon;
|
||||
} theme_cache;
|
||||
|
||||
void _drag_node_exit();
|
||||
void _drag_node_input(const Ref<InputEvent> &p_input);
|
||||
|
||||
virtual void gui_input(const Ref<InputEvent> &p_event) override;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "scene/main/window.h"
|
||||
|
||||
Size2 ScrollContainer::get_minimum_size() const {
|
||||
Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
|
||||
Size2 min_size;
|
||||
|
||||
// Calculated in this function, as it needs to traverse all child controls once to calculate;
|
||||
@ -77,10 +76,16 @@ Size2 ScrollContainer::get_minimum_size() const {
|
||||
min_size.x += v_scroll->get_minimum_size().x;
|
||||
}
|
||||
|
||||
min_size += sb->get_minimum_size();
|
||||
min_size += theme_cache.bg_style->get_minimum_size();
|
||||
return min_size;
|
||||
}
|
||||
|
||||
void ScrollContainer::_update_theme_item_cache() {
|
||||
Container::_update_theme_item_cache();
|
||||
|
||||
theme_cache.bg_style = get_theme_stylebox(SNAME("bg"));
|
||||
}
|
||||
|
||||
void ScrollContainer::_cancel_drag() {
|
||||
set_physics_process_internal(false);
|
||||
drag_touching_deaccel = false;
|
||||
@ -271,9 +276,8 @@ void ScrollContainer::_reposition_children() {
|
||||
Size2 size = get_size();
|
||||
Point2 ofs;
|
||||
|
||||
Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
|
||||
size -= sb->get_minimum_size();
|
||||
ofs += sb->get_offset();
|
||||
size -= theme_cache.bg_style->get_minimum_size();
|
||||
ofs += theme_cache.bg_style->get_offset();
|
||||
bool rtl = is_layout_rtl();
|
||||
|
||||
if (h_scroll->is_visible_in_tree() && h_scroll->get_parent() == this) { //scrolls may have been moved out for reasons
|
||||
@ -337,8 +341,7 @@ void ScrollContainer::_notification(int p_what) {
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_DRAW: {
|
||||
Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
|
||||
draw_style_box(sb, Rect2(Vector2(), get_size()));
|
||||
draw_style_box(theme_cache.bg_style, Rect2(Vector2(), get_size()));
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||
@ -413,8 +416,7 @@ void ScrollContainer::_notification(int p_what) {
|
||||
|
||||
void ScrollContainer::update_scrollbars() {
|
||||
Size2 size = get_size();
|
||||
Ref<StyleBox> sb = get_theme_stylebox(SNAME("bg"));
|
||||
size -= sb->get_minimum_size();
|
||||
size -= theme_cache.bg_style->get_minimum_size();
|
||||
|
||||
Size2 hmin = h_scroll->get_combined_minimum_size();
|
||||
Size2 vmin = v_scroll->get_combined_minimum_size();
|
||||
|
@ -69,9 +69,14 @@ private:
|
||||
int deadzone = 0;
|
||||
bool follow_focus = false;
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> bg_style;
|
||||
} theme_cache;
|
||||
|
||||
void _cancel_drag();
|
||||
|
||||
protected:
|
||||
virtual void _update_theme_item_cache() override;
|
||||
Size2 get_minimum_size() const override;
|
||||
|
||||
void _gui_focus_changed(Control *p_control);
|
||||
|
@ -33,24 +33,30 @@
|
||||
Size2 Separator::get_minimum_size() const {
|
||||
Size2 ms(3, 3);
|
||||
if (orientation == VERTICAL) {
|
||||
ms.x = get_theme_constant(SNAME("separation"));
|
||||
ms.x = theme_cache.separation;
|
||||
} else { // HORIZONTAL
|
||||
ms.y = get_theme_constant(SNAME("separation"));
|
||||
ms.y = theme_cache.separation;
|
||||
}
|
||||
return ms;
|
||||
}
|
||||
|
||||
void Separator::_update_theme_item_cache() {
|
||||
Control::_update_theme_item_cache();
|
||||
|
||||
theme_cache.separation = get_theme_constant(SNAME("separation"));
|
||||
theme_cache.separator_style = get_theme_stylebox(SNAME("separator"));
|
||||
}
|
||||
|
||||
void Separator::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
Size2i size = get_size();
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("separator"));
|
||||
Size2i ssize = style->get_minimum_size() + style->get_center_size();
|
||||
Size2i ssize = theme_cache.separator_style->get_minimum_size() + theme_cache.separator_style->get_center_size();
|
||||
|
||||
if (orientation == VERTICAL) {
|
||||
style->draw(get_canvas_item(), Rect2((size.x - ssize.x) / 2, 0, ssize.x, size.y));
|
||||
theme_cache.separator_style->draw(get_canvas_item(), Rect2((size.x - ssize.x) / 2, 0, ssize.x, size.y));
|
||||
} else {
|
||||
style->draw(get_canvas_item(), Rect2(0, (size.y - ssize.y) / 2, size.x, ssize.y));
|
||||
theme_cache.separator_style->draw(get_canvas_item(), Rect2(0, (size.y - ssize.y) / 2, size.x, ssize.y));
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
@ -35,8 +35,16 @@
|
||||
class Separator : public Control {
|
||||
GDCLASS(Separator, Control);
|
||||
|
||||
struct ThemeCache {
|
||||
int separation = 0;
|
||||
Ref<StyleBox> separator_style;
|
||||
} theme_cache;
|
||||
|
||||
protected:
|
||||
Orientation orientation = Orientation::HORIZONTAL;
|
||||
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
|
@ -33,11 +33,8 @@
|
||||
#include "core/os/keyboard.h"
|
||||
|
||||
Size2 Slider::get_minimum_size() const {
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("slider"));
|
||||
Size2i ss = style->get_minimum_size() + style->get_center_size();
|
||||
|
||||
Ref<Texture2D> grabber = get_theme_icon(SNAME("grabber"));
|
||||
Size2i rs = grabber->get_size();
|
||||
Size2i ss = theme_cache.slider_style->get_minimum_size() + theme_cache.slider_style->get_center_size();
|
||||
Size2i rs = theme_cache.grabber_icon->get_size();
|
||||
|
||||
if (orientation == HORIZONTAL) {
|
||||
return Size2i(ss.width, MAX(ss.height, rs.height));
|
||||
@ -58,7 +55,13 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
|
||||
if (mb.is_valid()) {
|
||||
if (mb->get_button_index() == MouseButton::LEFT) {
|
||||
if (mb->is_pressed()) {
|
||||
Ref<Texture2D> grabber = get_theme_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber");
|
||||
Ref<Texture2D> grabber;
|
||||
if (mouse_inside || has_focus()) {
|
||||
grabber = theme_cache.grabber_hl_icon;
|
||||
} else {
|
||||
grabber = theme_cache.grabber_icon;
|
||||
}
|
||||
|
||||
grab.pos = orientation == VERTICAL ? mb->get_position().y : mb->get_position().x;
|
||||
|
||||
double grab_width = (double)grabber->get_size().width;
|
||||
@ -95,7 +98,7 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
|
||||
if (mm.is_valid()) {
|
||||
if (grab.active) {
|
||||
Size2i size = get_size();
|
||||
Ref<Texture2D> grabber = get_theme_icon(SNAME("grabber"));
|
||||
Ref<Texture2D> grabber = theme_cache.grabber_icon;
|
||||
double motion = (orientation == VERTICAL ? mm->get_position().y : mm->get_position().x) - grab.pos;
|
||||
if (orientation == VERTICAL) {
|
||||
motion = -motion;
|
||||
@ -145,6 +148,19 @@ void Slider::gui_input(const Ref<InputEvent> &p_event) {
|
||||
}
|
||||
}
|
||||
|
||||
void Slider::_update_theme_item_cache() {
|
||||
Range::_update_theme_item_cache();
|
||||
|
||||
theme_cache.slider_style = get_theme_stylebox(SNAME("slider"));
|
||||
theme_cache.grabber_area_style = get_theme_stylebox(SNAME("grabber_area"));
|
||||
theme_cache.grabber_area_hl_style = get_theme_stylebox(SNAME("grabber_area_highlight"));
|
||||
|
||||
theme_cache.grabber_icon = get_theme_icon(SNAME("grabber"));
|
||||
theme_cache.grabber_hl_icon = get_theme_icon(SNAME("grabber_highlight"));
|
||||
theme_cache.grabber_disabled_icon = get_theme_icon(SNAME("grabber_disabled"));
|
||||
theme_cache.tick_icon = get_theme_icon(SNAME("tick"));
|
||||
}
|
||||
|
||||
void Slider::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
@ -171,13 +187,30 @@ void Slider::_notification(int p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
RID ci = get_canvas_item();
|
||||
Size2i size = get_size();
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("slider"));
|
||||
bool highlighted = mouse_inside || has_focus();
|
||||
Ref<StyleBox> grabber_area = get_theme_stylebox(highlighted ? "grabber_area_highlight" : "grabber_area");
|
||||
Ref<Texture2D> grabber = get_theme_icon(editable ? (highlighted ? "grabber_highlight" : "grabber") : "grabber_disabled");
|
||||
Ref<Texture2D> tick = get_theme_icon(SNAME("tick"));
|
||||
double ratio = Math::is_nan(get_as_ratio()) ? 0 : get_as_ratio();
|
||||
|
||||
Ref<StyleBox> style = theme_cache.slider_style;
|
||||
Ref<Texture2D> tick = theme_cache.tick_icon;
|
||||
|
||||
bool highlighted = mouse_inside || has_focus();
|
||||
Ref<Texture2D> grabber;
|
||||
if (editable) {
|
||||
if (highlighted) {
|
||||
grabber = theme_cache.grabber_hl_icon;
|
||||
} else {
|
||||
grabber = theme_cache.grabber_icon;
|
||||
}
|
||||
} else {
|
||||
grabber = theme_cache.grabber_disabled_icon;
|
||||
}
|
||||
|
||||
Ref<StyleBox> grabber_area;
|
||||
if (highlighted) {
|
||||
grabber_area = theme_cache.grabber_area_hl_style;
|
||||
} else {
|
||||
grabber_area = theme_cache.grabber_area_style;
|
||||
}
|
||||
|
||||
if (orientation == VERTICAL) {
|
||||
int widget_width = style->get_minimum_size().width + style->get_center_size().width;
|
||||
double areasize = size.height - grabber->get_size().height;
|
||||
|
@ -49,11 +49,24 @@ class Slider : public Range {
|
||||
bool editable = true;
|
||||
bool scrollable = true;
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> slider_style;
|
||||
Ref<StyleBox> grabber_area_style;
|
||||
Ref<StyleBox> grabber_area_hl_style;
|
||||
|
||||
Ref<Texture2D> grabber_icon;
|
||||
Ref<Texture2D> grabber_hl_icon;
|
||||
Ref<Texture2D> grabber_disabled_icon;
|
||||
Ref<Texture2D> tick_icon;
|
||||
} theme_cache;
|
||||
|
||||
protected:
|
||||
bool ticks_on_borders = false;
|
||||
|
||||
virtual void gui_input(const Ref<InputEvent> &p_event) override;
|
||||
virtual void _update_theme_item_cache() override;
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
bool ticks_on_borders = false;
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
|
@ -210,25 +210,29 @@ inline void SpinBox::_adjust_width_for_icon(const Ref<Texture2D> &icon) {
|
||||
}
|
||||
}
|
||||
|
||||
void SpinBox::_update_theme_item_cache() {
|
||||
Range::_update_theme_item_cache();
|
||||
|
||||
theme_cache.updown_icon = get_theme_icon(SNAME("updown"));
|
||||
}
|
||||
|
||||
void SpinBox::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
Ref<Texture2D> updown = get_theme_icon(SNAME("updown"));
|
||||
|
||||
_adjust_width_for_icon(updown);
|
||||
_adjust_width_for_icon(theme_cache.updown_icon);
|
||||
|
||||
RID ci = get_canvas_item();
|
||||
Size2i size = get_size();
|
||||
|
||||
if (is_layout_rtl()) {
|
||||
updown->draw(ci, Point2i(0, (size.height - updown->get_height()) / 2));
|
||||
theme_cache.updown_icon->draw(ci, Point2i(0, (size.height - theme_cache.updown_icon->get_height()) / 2));
|
||||
} else {
|
||||
updown->draw(ci, Point2i(size.width - updown->get_width(), (size.height - updown->get_height()) / 2));
|
||||
theme_cache.updown_icon->draw(ci, Point2i(size.width - theme_cache.updown_icon->get_width(), (size.height - theme_cache.updown_icon->get_height()) / 2));
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
_adjust_width_for_icon(get_theme_icon(SNAME("updown")));
|
||||
_adjust_width_for_icon(theme_cache.updown_icon);
|
||||
_value_changed(0);
|
||||
} break;
|
||||
|
||||
|
@ -69,9 +69,14 @@ class SpinBox : public Range {
|
||||
|
||||
inline void _adjust_width_for_icon(const Ref<Texture2D> &icon);
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<Texture2D> updown_icon;
|
||||
} theme_cache;
|
||||
|
||||
protected:
|
||||
virtual void gui_input(const Ref<InputEvent> &p_event) override;
|
||||
|
||||
virtual void _update_theme_item_cache() override;
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
@ -76,9 +76,7 @@ void SplitContainer::_resort() {
|
||||
bool second_expanded = (vertical ? second->get_v_size_flags() : second->get_h_size_flags()) & SIZE_EXPAND;
|
||||
|
||||
// Determine the separation between items
|
||||
Ref<Texture2D> g = get_theme_icon(SNAME("grabber"));
|
||||
int sep = get_theme_constant(SNAME("separation"));
|
||||
sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
|
||||
int sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(theme_cache.separation, vertical ? theme_cache.grabber_icon->get_height() : theme_cache.grabber_icon->get_width()) : 0;
|
||||
|
||||
// Compute the minimum size
|
||||
Size2 ms_first = first->get_combined_minimum_size();
|
||||
@ -131,9 +129,7 @@ Size2 SplitContainer::get_minimum_size() const {
|
||||
/* Calculate MINIMUM SIZE */
|
||||
|
||||
Size2i minimum;
|
||||
Ref<Texture2D> g = get_theme_icon(SNAME("grabber"));
|
||||
int sep = get_theme_constant(SNAME("separation"));
|
||||
sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
|
||||
int sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(theme_cache.separation, vertical ? theme_cache.grabber_icon->get_height() : theme_cache.grabber_icon->get_width()) : 0;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (!_getch(i)) {
|
||||
@ -162,6 +158,14 @@ Size2 SplitContainer::get_minimum_size() const {
|
||||
return minimum;
|
||||
}
|
||||
|
||||
void SplitContainer::_update_theme_item_cache() {
|
||||
Container::_update_theme_item_cache();
|
||||
|
||||
theme_cache.separation = get_theme_constant(SNAME("separation"));
|
||||
theme_cache.autohide = get_theme_constant(SNAME("autohide"));
|
||||
theme_cache.grabber_icon = get_theme_icon(SNAME("grabber"));
|
||||
}
|
||||
|
||||
void SplitContainer::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_TRANSLATION_CHANGED:
|
||||
@ -175,7 +179,7 @@ void SplitContainer::_notification(int p_what) {
|
||||
|
||||
case NOTIFICATION_MOUSE_EXIT: {
|
||||
mouse_inside = false;
|
||||
if (get_theme_constant(SNAME("autohide"))) {
|
||||
if (theme_cache.autohide) {
|
||||
queue_redraw();
|
||||
}
|
||||
} break;
|
||||
@ -185,7 +189,7 @@ void SplitContainer::_notification(int p_what) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (collapsed || (!dragging && !mouse_inside && get_theme_constant(SNAME("autohide")))) {
|
||||
if (collapsed || (!dragging && !mouse_inside && theme_cache.autohide)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -193,8 +197,8 @@ void SplitContainer::_notification(int p_what) {
|
||||
return;
|
||||
}
|
||||
|
||||
int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_theme_constant(SNAME("separation")) : 0;
|
||||
Ref<Texture2D> tex = get_theme_icon(SNAME("grabber"));
|
||||
int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? theme_cache.separation : 0;
|
||||
Ref<Texture2D> tex = theme_cache.grabber_icon;
|
||||
Size2 size = get_size();
|
||||
|
||||
if (vertical) {
|
||||
@ -222,16 +226,14 @@ void SplitContainer::gui_input(const Ref<InputEvent> &p_event) {
|
||||
if (mb.is_valid()) {
|
||||
if (mb->get_button_index() == MouseButton::LEFT) {
|
||||
if (mb->is_pressed()) {
|
||||
int sep = get_theme_constant(SNAME("separation"));
|
||||
|
||||
if (vertical) {
|
||||
if (mb->get_position().y > middle_sep && mb->get_position().y < middle_sep + sep) {
|
||||
if (mb->get_position().y > middle_sep && mb->get_position().y < middle_sep + theme_cache.separation) {
|
||||
dragging = true;
|
||||
drag_from = mb->get_position().y;
|
||||
drag_ofs = split_offset;
|
||||
}
|
||||
} else {
|
||||
if (mb->get_position().x > middle_sep && mb->get_position().x < middle_sep + sep) {
|
||||
if (mb->get_position().x > middle_sep && mb->get_position().x < middle_sep + theme_cache.separation) {
|
||||
dragging = true;
|
||||
drag_from = mb->get_position().x;
|
||||
drag_ofs = split_offset;
|
||||
@ -248,14 +250,14 @@ void SplitContainer::gui_input(const Ref<InputEvent> &p_event) {
|
||||
if (mm.is_valid()) {
|
||||
bool mouse_inside_state = false;
|
||||
if (vertical) {
|
||||
mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + get_theme_constant(SNAME("separation"));
|
||||
mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + theme_cache.separation;
|
||||
} else {
|
||||
mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + get_theme_constant(SNAME("separation"));
|
||||
mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + theme_cache.separation;
|
||||
}
|
||||
|
||||
if (mouse_inside != mouse_inside_state) {
|
||||
mouse_inside = mouse_inside_state;
|
||||
if (get_theme_constant(SNAME("autohide"))) {
|
||||
if (theme_cache.autohide) {
|
||||
queue_redraw();
|
||||
}
|
||||
}
|
||||
@ -281,14 +283,12 @@ Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const
|
||||
}
|
||||
|
||||
if (!collapsed && _getch(0) && _getch(1) && dragger_visibility == DRAGGER_VISIBLE) {
|
||||
int sep = get_theme_constant(SNAME("separation"));
|
||||
|
||||
if (vertical) {
|
||||
if (p_pos.y > middle_sep && p_pos.y < middle_sep + sep) {
|
||||
if (p_pos.y > middle_sep && p_pos.y < middle_sep + theme_cache.separation) {
|
||||
return CURSOR_VSPLIT;
|
||||
}
|
||||
} else {
|
||||
if (p_pos.x > middle_sep && p_pos.x < middle_sep + sep) {
|
||||
if (p_pos.x > middle_sep && p_pos.x < middle_sep + theme_cache.separation) {
|
||||
return CURSOR_HSPLIT;
|
||||
}
|
||||
}
|
||||
|
@ -55,12 +55,20 @@ private:
|
||||
DraggerVisibility dragger_visibility = DRAGGER_VISIBLE;
|
||||
bool mouse_inside = false;
|
||||
|
||||
struct ThemeCache {
|
||||
int separation = 0;
|
||||
int autohide = 0;
|
||||
Ref<Texture2D> grabber_icon;
|
||||
} theme_cache;
|
||||
|
||||
Control *_getch(int p_idx) const;
|
||||
|
||||
void _resort();
|
||||
|
||||
protected:
|
||||
virtual void gui_input(const Ref<InputEvent> &p_event) override;
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
|
@ -44,14 +44,7 @@ Size2 TabBar::get_minimum_size() const {
|
||||
return ms;
|
||||
}
|
||||
|
||||
Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
|
||||
Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
|
||||
Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
|
||||
Ref<StyleBox> button_highlight = get_theme_stylebox(SNAME("button_highlight"));
|
||||
Ref<Texture2D> close = get_theme_icon(SNAME("close"));
|
||||
int hseparation = get_theme_constant(SNAME("h_separation"));
|
||||
|
||||
int y_margin = MAX(MAX(tab_unselected->get_minimum_size().height, tab_selected->get_minimum_size().height), tab_disabled->get_minimum_size().height);
|
||||
int y_margin = MAX(MAX(theme_cache.tab_unselected_style->get_minimum_size().height, theme_cache.tab_selected_style->get_minimum_size().height), theme_cache.tab_disabled_style->get_minimum_size().height);
|
||||
|
||||
for (int i = 0; i < tabs.size(); i++) {
|
||||
if (tabs[i].hidden) {
|
||||
@ -62,22 +55,22 @@ Size2 TabBar::get_minimum_size() const {
|
||||
|
||||
Ref<StyleBox> style;
|
||||
if (tabs[i].disabled) {
|
||||
style = tab_disabled;
|
||||
style = theme_cache.tab_disabled_style;
|
||||
} else if (current == i) {
|
||||
style = tab_selected;
|
||||
style = theme_cache.tab_selected_style;
|
||||
} else {
|
||||
style = tab_unselected;
|
||||
style = theme_cache.tab_unselected_style;
|
||||
}
|
||||
ms.width += style->get_minimum_size().width;
|
||||
|
||||
Ref<Texture2D> tex = tabs[i].icon;
|
||||
if (tex.is_valid()) {
|
||||
ms.height = MAX(ms.height, tex->get_size().height + y_margin);
|
||||
ms.width += tex->get_size().width + hseparation;
|
||||
ms.width += tex->get_size().width + theme_cache.h_separation;
|
||||
}
|
||||
|
||||
if (!tabs[i].text.is_empty()) {
|
||||
ms.width += tabs[i].size_text + hseparation;
|
||||
ms.width += tabs[i].size_text + theme_cache.h_separation;
|
||||
}
|
||||
ms.height = MAX(ms.height, tabs[i].text_buf->get_size().y + y_margin);
|
||||
|
||||
@ -87,22 +80,22 @@ Size2 TabBar::get_minimum_size() const {
|
||||
Ref<Texture2D> rb = tabs[i].right_button;
|
||||
|
||||
if (close_visible) {
|
||||
ms.width += button_highlight->get_minimum_size().width + rb->get_width();
|
||||
ms.width += theme_cache.button_hl_style->get_minimum_size().width + rb->get_width();
|
||||
} else {
|
||||
ms.width += button_highlight->get_margin(SIDE_LEFT) + rb->get_width() + hseparation;
|
||||
ms.width += theme_cache.button_hl_style->get_margin(SIDE_LEFT) + rb->get_width() + theme_cache.h_separation;
|
||||
}
|
||||
|
||||
ms.height = MAX(ms.height, rb->get_height() + y_margin);
|
||||
}
|
||||
|
||||
if (close_visible) {
|
||||
ms.width += button_highlight->get_margin(SIDE_LEFT) + close->get_width() + hseparation;
|
||||
ms.width += theme_cache.button_hl_style->get_margin(SIDE_LEFT) + theme_cache.close_icon->get_width() + theme_cache.h_separation;
|
||||
|
||||
ms.height = MAX(ms.height, close->get_height() + y_margin);
|
||||
ms.height = MAX(ms.height, theme_cache.close_icon->get_height() + y_margin);
|
||||
}
|
||||
|
||||
if (ms.width - ofs > style->get_minimum_size().width) {
|
||||
ms.width -= hseparation;
|
||||
ms.width -= theme_cache.h_separation;
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,16 +115,13 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
|
||||
Point2 pos = mm->get_position();
|
||||
|
||||
if (buttons_visible) {
|
||||
Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
|
||||
Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
|
||||
|
||||
if (is_layout_rtl()) {
|
||||
if (pos.x < decr->get_width()) {
|
||||
if (pos.x < theme_cache.decrement_icon->get_width()) {
|
||||
if (highlight_arrow != 1) {
|
||||
highlight_arrow = 1;
|
||||
queue_redraw();
|
||||
}
|
||||
} else if (pos.x < incr->get_width() + decr->get_width()) {
|
||||
} else if (pos.x < theme_cache.increment_icon->get_width() + theme_cache.decrement_icon->get_width()) {
|
||||
if (highlight_arrow != 0) {
|
||||
highlight_arrow = 0;
|
||||
queue_redraw();
|
||||
@ -141,8 +131,8 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
|
||||
queue_redraw();
|
||||
}
|
||||
} else {
|
||||
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
|
||||
if (pos.x > limit_minus_buttons + decr->get_width()) {
|
||||
int limit_minus_buttons = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
|
||||
if (pos.x > limit_minus_buttons + theme_cache.decrement_icon->get_width()) {
|
||||
if (highlight_arrow != 1) {
|
||||
highlight_arrow = 1;
|
||||
queue_redraw();
|
||||
@ -214,18 +204,15 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
|
||||
Point2 pos = mb->get_position();
|
||||
|
||||
if (buttons_visible) {
|
||||
Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
|
||||
Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
|
||||
|
||||
if (is_layout_rtl()) {
|
||||
if (pos.x < decr->get_width()) {
|
||||
if (pos.x < theme_cache.decrement_icon->get_width()) {
|
||||
if (missing_right) {
|
||||
offset++;
|
||||
_update_cache();
|
||||
queue_redraw();
|
||||
}
|
||||
return;
|
||||
} else if (pos.x < incr->get_width() + decr->get_width()) {
|
||||
} else if (pos.x < theme_cache.increment_icon->get_width() + theme_cache.decrement_icon->get_width()) {
|
||||
if (offset > 0) {
|
||||
offset--;
|
||||
_update_cache();
|
||||
@ -234,8 +221,8 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
int limit = get_size().width - incr->get_width() - decr->get_width();
|
||||
if (pos.x > limit + decr->get_width()) {
|
||||
int limit = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
|
||||
if (pos.x > limit + theme_cache.decrement_icon->get_width()) {
|
||||
if (missing_right) {
|
||||
offset++;
|
||||
_update_cache();
|
||||
@ -299,9 +286,6 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) {
|
||||
}
|
||||
|
||||
void TabBar::_shape(int p_tab) {
|
||||
Ref<Font> font = get_theme_font(SNAME("font"));
|
||||
int font_size = get_theme_font_size(SNAME("font_size"));
|
||||
|
||||
tabs.write[p_tab].xl_text = atr(tabs[p_tab].text);
|
||||
tabs.write[p_tab].text_buf->clear();
|
||||
tabs.write[p_tab].text_buf->set_width(-1);
|
||||
@ -311,7 +295,37 @@ void TabBar::_shape(int p_tab) {
|
||||
tabs.write[p_tab].text_buf->set_direction((TextServer::Direction)tabs[p_tab].text_direction);
|
||||
}
|
||||
|
||||
tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, font, font_size, tabs[p_tab].language);
|
||||
tabs.write[p_tab].text_buf->add_string(tabs[p_tab].xl_text, theme_cache.font, theme_cache.font_size, tabs[p_tab].language);
|
||||
}
|
||||
|
||||
void TabBar::_update_theme_item_cache() {
|
||||
Control::_update_theme_item_cache();
|
||||
|
||||
theme_cache.h_separation = get_theme_constant(SNAME("h_separation"));
|
||||
|
||||
theme_cache.tab_unselected_style = get_theme_stylebox(SNAME("tab_unselected"));
|
||||
theme_cache.tab_selected_style = get_theme_stylebox(SNAME("tab_selected"));
|
||||
theme_cache.tab_disabled_style = get_theme_stylebox(SNAME("tab_disabled"));
|
||||
|
||||
theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
|
||||
theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
|
||||
theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
|
||||
theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
|
||||
theme_cache.drop_mark_icon = get_theme_icon(SNAME("drop_mark"));
|
||||
theme_cache.drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
|
||||
|
||||
theme_cache.font = get_theme_font(SNAME("font"));
|
||||
theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
|
||||
theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
|
||||
theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
|
||||
theme_cache.font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
|
||||
theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
|
||||
theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
|
||||
theme_cache.close_icon = get_theme_icon(SNAME("close"));
|
||||
theme_cache.button_pressed_style = get_theme_stylebox(SNAME("button_pressed"));
|
||||
theme_cache.button_hl_style = get_theme_stylebox(SNAME("button_highlight"));
|
||||
}
|
||||
|
||||
void TabBar::_notification(int p_what) {
|
||||
@ -352,18 +366,9 @@ void TabBar::_notification(int p_what) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
|
||||
Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
|
||||
Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
|
||||
Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
|
||||
Color font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
|
||||
Color font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
|
||||
Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
|
||||
Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
|
||||
|
||||
bool rtl = is_layout_rtl();
|
||||
Vector2 size = get_size();
|
||||
int limit_minus_buttons = size.width - incr->get_width() - decr->get_width();
|
||||
int limit_minus_buttons = size.width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
|
||||
|
||||
int ofs = tabs[offset].ofs_cache;
|
||||
|
||||
@ -378,14 +383,14 @@ void TabBar::_notification(int p_what) {
|
||||
Color col;
|
||||
|
||||
if (tabs[i].disabled) {
|
||||
sb = tab_disabled;
|
||||
col = font_disabled_color;
|
||||
sb = theme_cache.tab_disabled_style;
|
||||
col = theme_cache.font_disabled_color;
|
||||
} else if (i == current) {
|
||||
sb = tab_selected;
|
||||
col = font_selected_color;
|
||||
sb = theme_cache.tab_selected_style;
|
||||
col = theme_cache.font_selected_color;
|
||||
} else {
|
||||
sb = tab_unselected;
|
||||
col = font_unselected_color;
|
||||
sb = theme_cache.tab_unselected_style;
|
||||
col = theme_cache.font_unselected_color;
|
||||
}
|
||||
|
||||
_draw_tab(sb, col, i, rtl ? size.width - ofs - tabs[i].size_cache : ofs);
|
||||
@ -396,41 +401,38 @@ void TabBar::_notification(int p_what) {
|
||||
|
||||
// Draw selected tab in the front, but only if it's visible.
|
||||
if (current >= offset && current <= max_drawn_tab && !tabs[current].hidden) {
|
||||
Ref<StyleBox> sb = tabs[current].disabled ? tab_disabled : tab_selected;
|
||||
Ref<StyleBox> sb = tabs[current].disabled ? theme_cache.tab_disabled_style : theme_cache.tab_selected_style;
|
||||
float x = rtl ? size.width - tabs[current].ofs_cache - tabs[current].size_cache : tabs[current].ofs_cache;
|
||||
|
||||
_draw_tab(sb, font_selected_color, current, x);
|
||||
_draw_tab(sb, theme_cache.font_selected_color, current, x);
|
||||
}
|
||||
|
||||
if (buttons_visible) {
|
||||
Ref<Texture2D> incr_hl = get_theme_icon(SNAME("increment_highlight"));
|
||||
Ref<Texture2D> decr_hl = get_theme_icon(SNAME("decrement_highlight"));
|
||||
|
||||
int vofs = (size.height - incr->get_size().height) / 2;
|
||||
int vofs = (size.height - theme_cache.increment_icon->get_size().height) / 2;
|
||||
|
||||
if (rtl) {
|
||||
if (missing_right) {
|
||||
draw_texture(highlight_arrow == 1 ? decr_hl : decr, Point2(0, vofs));
|
||||
draw_texture(highlight_arrow == 1 ? theme_cache.decrement_hl_icon : theme_cache.decrement_icon, Point2(0, vofs));
|
||||
} else {
|
||||
draw_texture(decr, Point2(0, vofs), Color(1, 1, 1, 0.5));
|
||||
draw_texture(theme_cache.decrement_icon, Point2(0, vofs), Color(1, 1, 1, 0.5));
|
||||
}
|
||||
|
||||
if (offset > 0) {
|
||||
draw_texture(highlight_arrow == 0 ? incr_hl : incr, Point2(incr->get_size().width, vofs));
|
||||
draw_texture(highlight_arrow == 0 ? theme_cache.increment_hl_icon : theme_cache.increment_icon, Point2(theme_cache.increment_icon->get_size().width, vofs));
|
||||
} else {
|
||||
draw_texture(incr, Point2(incr->get_size().width, vofs), Color(1, 1, 1, 0.5));
|
||||
draw_texture(theme_cache.increment_icon, Point2(theme_cache.increment_icon->get_size().width, vofs), Color(1, 1, 1, 0.5));
|
||||
}
|
||||
} else {
|
||||
if (offset > 0) {
|
||||
draw_texture(highlight_arrow == 0 ? decr_hl : decr, Point2(limit_minus_buttons, vofs));
|
||||
draw_texture(highlight_arrow == 0 ? theme_cache.decrement_hl_icon : theme_cache.decrement_icon, Point2(limit_minus_buttons, vofs));
|
||||
} else {
|
||||
draw_texture(decr, Point2(limit_minus_buttons, vofs), Color(1, 1, 1, 0.5));
|
||||
draw_texture(theme_cache.decrement_icon, Point2(limit_minus_buttons, vofs), Color(1, 1, 1, 0.5));
|
||||
}
|
||||
|
||||
if (missing_right) {
|
||||
draw_texture(highlight_arrow == 1 ? incr_hl : incr, Point2(limit_minus_buttons + decr->get_size().width, vofs));
|
||||
draw_texture(highlight_arrow == 1 ? theme_cache.increment_hl_icon : theme_cache.increment_icon, Point2(limit_minus_buttons + theme_cache.decrement_icon->get_size().width, vofs));
|
||||
} else {
|
||||
draw_texture(incr, Point2(limit_minus_buttons + decr->get_size().width, vofs), Color(1, 1, 1, 0.5));
|
||||
draw_texture(theme_cache.increment_icon, Point2(limit_minus_buttons + theme_cache.decrement_icon->get_size().width, vofs), Color(1, 1, 1, 0.5));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -462,10 +464,7 @@ void TabBar::_notification(int p_what) {
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Texture2D> drop_mark = get_theme_icon(SNAME("drop_mark"));
|
||||
Color drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
|
||||
|
||||
drop_mark->draw(get_canvas_item(), Point2(x - drop_mark->get_width() / 2, (size.height - drop_mark->get_height()) / 2), drop_mark_color);
|
||||
theme_cache.drop_mark_icon->draw(get_canvas_item(), Point2(x - theme_cache.drop_mark_icon->get_width() / 2, (size.height - theme_cache.drop_mark_icon->get_height()) / 2), theme_cache.drop_mark_color);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
@ -475,10 +474,6 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
|
||||
RID ci = get_canvas_item();
|
||||
bool rtl = is_layout_rtl();
|
||||
|
||||
Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
int outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
int hseparation = get_theme_constant(SNAME("h_separation"));
|
||||
|
||||
Rect2 sb_rect = Rect2(p_x, 0, tabs[p_index].size_cache, get_size().height);
|
||||
p_tab_style->draw(ci, sb_rect);
|
||||
|
||||
@ -491,7 +486,7 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
|
||||
if (icon.is_valid()) {
|
||||
icon->draw(ci, Point2i(rtl ? p_x - icon->get_width() : p_x, p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - icon->get_height()) / 2));
|
||||
|
||||
p_x = rtl ? p_x - icon->get_width() - hseparation : p_x + icon->get_width() + hseparation;
|
||||
p_x = rtl ? p_x - icon->get_width() - theme_cache.h_separation : p_x + icon->get_width() + theme_cache.h_separation;
|
||||
}
|
||||
|
||||
// Draw the text.
|
||||
@ -499,17 +494,17 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
|
||||
Point2i text_pos = Point2i(rtl ? p_x - tabs[p_index].size_text : p_x,
|
||||
p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - tabs[p_index].text_buf->get_size().y) / 2);
|
||||
|
||||
if (outline_size > 0 && font_outline_color.a > 0) {
|
||||
tabs[p_index].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
|
||||
if (theme_cache.outline_size > 0 && theme_cache.font_outline_color.a > 0) {
|
||||
tabs[p_index].text_buf->draw_outline(ci, text_pos, theme_cache.outline_size, theme_cache.font_outline_color);
|
||||
}
|
||||
tabs[p_index].text_buf->draw(ci, text_pos, p_font_color);
|
||||
|
||||
p_x = rtl ? p_x - tabs[p_index].size_text - hseparation : p_x + tabs[p_index].size_text + hseparation;
|
||||
p_x = rtl ? p_x - tabs[p_index].size_text - theme_cache.h_separation : p_x + tabs[p_index].size_text + theme_cache.h_separation;
|
||||
}
|
||||
|
||||
// Draw and calculate rect of the right button.
|
||||
if (tabs[p_index].right_button.is_valid()) {
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("button_highlight"));
|
||||
Ref<StyleBox> style = theme_cache.button_hl_style;
|
||||
Ref<Texture2D> rb = tabs[p_index].right_button;
|
||||
|
||||
Rect2 rb_rect;
|
||||
@ -521,7 +516,7 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
|
||||
|
||||
if (rb_hover == p_index) {
|
||||
if (rb_pressing) {
|
||||
get_theme_stylebox(SNAME("button_pressed"))->draw(ci, rb_rect);
|
||||
theme_cache.button_pressed_style->draw(ci, rb_rect);
|
||||
} else {
|
||||
style->draw(ci, rb_rect);
|
||||
}
|
||||
@ -534,8 +529,8 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
|
||||
|
||||
// Draw and calculate rect of the close button.
|
||||
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_index == current)) {
|
||||
Ref<StyleBox> style = get_theme_stylebox(SNAME("button_highlight"));
|
||||
Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
|
||||
Ref<StyleBox> style = theme_cache.button_hl_style;
|
||||
Ref<Texture2D> cb = theme_cache.close_icon;
|
||||
|
||||
Rect2 cb_rect;
|
||||
cb_rect.size = style->get_minimum_size() + cb->get_size();
|
||||
@ -546,7 +541,7 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
|
||||
|
||||
if (!tabs[p_index].disabled && cb_hover == p_index) {
|
||||
if (cb_pressing) {
|
||||
get_theme_stylebox(SNAME("button_pressed"))->draw(ci, cb_rect);
|
||||
theme_cache.button_pressed_style->draw(ci, cb_rect);
|
||||
} else {
|
||||
style->draw(ci, cb_rect);
|
||||
}
|
||||
@ -849,14 +844,8 @@ void TabBar::_update_cache() {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
|
||||
Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
|
||||
Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
|
||||
Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
|
||||
Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
|
||||
|
||||
int limit = get_size().width;
|
||||
int limit_minus_buttons = limit - incr->get_width() - decr->get_width();
|
||||
int limit_minus_buttons = limit - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
|
||||
|
||||
int w = 0;
|
||||
|
||||
@ -1258,52 +1247,47 @@ void TabBar::move_tab(int p_from, int p_to) {
|
||||
int TabBar::get_tab_width(int p_idx) const {
|
||||
ERR_FAIL_INDEX_V(p_idx, tabs.size(), 0);
|
||||
|
||||
Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
|
||||
Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
|
||||
Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
|
||||
int hseparation = get_theme_constant(SNAME("h_separation"));
|
||||
|
||||
Ref<StyleBox> style;
|
||||
|
||||
if (tabs[p_idx].disabled) {
|
||||
style = tab_disabled;
|
||||
style = theme_cache.tab_disabled_style;
|
||||
} else if (current == p_idx) {
|
||||
style = tab_selected;
|
||||
style = theme_cache.tab_selected_style;
|
||||
} else {
|
||||
style = tab_unselected;
|
||||
style = theme_cache.tab_unselected_style;
|
||||
}
|
||||
int x = style->get_minimum_size().width;
|
||||
|
||||
Ref<Texture2D> tex = tabs[p_idx].icon;
|
||||
if (tex.is_valid()) {
|
||||
x += tex->get_width() + hseparation;
|
||||
x += tex->get_width() + theme_cache.h_separation;
|
||||
}
|
||||
|
||||
if (!tabs[p_idx].text.is_empty()) {
|
||||
x += tabs[p_idx].size_text + hseparation;
|
||||
x += tabs[p_idx].size_text + theme_cache.h_separation;
|
||||
}
|
||||
|
||||
bool close_visible = cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_idx == current);
|
||||
|
||||
if (tabs[p_idx].right_button.is_valid()) {
|
||||
Ref<StyleBox> btn_style = get_theme_stylebox(SNAME("button_highlight"));
|
||||
Ref<StyleBox> btn_style = theme_cache.button_hl_style;
|
||||
Ref<Texture2D> rb = tabs[p_idx].right_button;
|
||||
|
||||
if (close_visible) {
|
||||
x += btn_style->get_minimum_size().width + rb->get_width();
|
||||
} else {
|
||||
x += btn_style->get_margin(SIDE_LEFT) + rb->get_width() + hseparation;
|
||||
x += btn_style->get_margin(SIDE_LEFT) + rb->get_width() + theme_cache.h_separation;
|
||||
}
|
||||
}
|
||||
|
||||
if (close_visible) {
|
||||
Ref<StyleBox> btn_style = get_theme_stylebox(SNAME("button_highlight"));
|
||||
Ref<Texture2D> cb = get_theme_icon(SNAME("close"));
|
||||
x += btn_style->get_margin(SIDE_LEFT) + cb->get_width() + hseparation;
|
||||
Ref<StyleBox> btn_style = theme_cache.button_hl_style;
|
||||
Ref<Texture2D> cb = theme_cache.close_icon;
|
||||
x += btn_style->get_margin(SIDE_LEFT) + cb->get_width() + theme_cache.h_separation;
|
||||
}
|
||||
|
||||
if (x > style->get_minimum_size().width) {
|
||||
x -= hseparation;
|
||||
x -= theme_cache.h_separation;
|
||||
}
|
||||
|
||||
return x;
|
||||
@ -1314,9 +1298,7 @@ void TabBar::_ensure_no_over_offset() {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
|
||||
Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
|
||||
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
|
||||
int limit_minus_buttons = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
|
||||
|
||||
int prev_offset = offset;
|
||||
|
||||
@ -1359,9 +1341,7 @@ void TabBar::ensure_tab_visible(int p_idx) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<Texture2D> incr = get_theme_icon(SNAME("increment"));
|
||||
Ref<Texture2D> decr = get_theme_icon(SNAME("decrement"));
|
||||
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
|
||||
int limit_minus_buttons = get_size().width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
|
||||
|
||||
int total_w = tabs[max_drawn_tab].ofs_cache - tabs[offset].ofs_cache;
|
||||
for (int i = max_drawn_tab; i <= p_idx; i++) {
|
||||
|
@ -104,6 +104,34 @@ private:
|
||||
bool scroll_to_selected = true;
|
||||
int tabs_rearrange_group = -1;
|
||||
|
||||
struct ThemeCache {
|
||||
int h_separation = 0;
|
||||
|
||||
Ref<StyleBox> tab_unselected_style;
|
||||
Ref<StyleBox> tab_selected_style;
|
||||
Ref<StyleBox> tab_disabled_style;
|
||||
|
||||
Ref<Texture2D> increment_icon;
|
||||
Ref<Texture2D> increment_hl_icon;
|
||||
Ref<Texture2D> decrement_icon;
|
||||
Ref<Texture2D> decrement_hl_icon;
|
||||
Ref<Texture2D> drop_mark_icon;
|
||||
Color drop_mark_color;
|
||||
|
||||
Ref<Font> font;
|
||||
int font_size;
|
||||
int outline_size = 0;
|
||||
|
||||
Color font_selected_color;
|
||||
Color font_unselected_color;
|
||||
Color font_disabled_color;
|
||||
Color font_outline_color;
|
||||
|
||||
Ref<Texture2D> close_icon;
|
||||
Ref<StyleBox> button_pressed_style;
|
||||
Ref<StyleBox> button_hl_style;
|
||||
} theme_cache;
|
||||
|
||||
int get_tab_width(int p_idx) const;
|
||||
void _ensure_no_over_offset();
|
||||
|
||||
@ -117,6 +145,7 @@ private:
|
||||
|
||||
protected:
|
||||
virtual void gui_input(const Ref<InputEvent> &p_event) override;
|
||||
virtual void _update_theme_item_cache() override;
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
@ -60,26 +60,24 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
|
||||
}
|
||||
|
||||
// Handle menu button.
|
||||
Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
|
||||
|
||||
if (is_layout_rtl()) {
|
||||
if (popup && pos.x < menu->get_width()) {
|
||||
if (popup && pos.x < theme_cache.menu_icon->get_width()) {
|
||||
emit_signal(SNAME("pre_popup_pressed"));
|
||||
|
||||
Vector2 popup_pos = get_screen_position();
|
||||
popup_pos.y += menu->get_height();
|
||||
popup_pos.y += theme_cache.menu_icon->get_height();
|
||||
|
||||
popup->set_position(popup_pos);
|
||||
popup->popup();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (popup && pos.x > size.width - menu->get_width()) {
|
||||
if (popup && pos.x > size.width - theme_cache.menu_icon->get_width()) {
|
||||
emit_signal(SNAME("pre_popup_pressed"));
|
||||
|
||||
Vector2 popup_pos = get_screen_position();
|
||||
popup_pos.x += size.width - popup->get_size().width;
|
||||
popup_pos.y += menu->get_height();
|
||||
popup_pos.y += theme_cache.menu_icon->get_height();
|
||||
|
||||
popup->set_position(popup_pos);
|
||||
popup->popup();
|
||||
@ -103,10 +101,9 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
|
||||
if (popup) {
|
||||
if (is_layout_rtl()) {
|
||||
if (pos.x <= menu->get_width()) {
|
||||
if (pos.x <= theme_cache.menu_icon->get_width()) {
|
||||
if (!menu_hovered) {
|
||||
menu_hovered = true;
|
||||
queue_redraw();
|
||||
@ -117,7 +114,7 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
|
||||
queue_redraw();
|
||||
}
|
||||
} else {
|
||||
if (pos.x >= size.width - menu->get_width()) {
|
||||
if (pos.x >= size.width - theme_cache.menu_icon->get_width()) {
|
||||
if (!menu_hovered) {
|
||||
menu_hovered = true;
|
||||
queue_redraw();
|
||||
@ -136,6 +133,41 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
|
||||
}
|
||||
}
|
||||
|
||||
void TabContainer::_update_theme_item_cache() {
|
||||
Container::_update_theme_item_cache();
|
||||
|
||||
theme_cache.side_margin = get_theme_constant(SNAME("side_margin"));
|
||||
|
||||
theme_cache.panel_style = get_theme_stylebox(SNAME("panel"));
|
||||
theme_cache.tabbar_style = get_theme_stylebox(SNAME("tabbar_background"));
|
||||
|
||||
theme_cache.menu_icon = get_theme_icon(SNAME("menu"));
|
||||
theme_cache.menu_hl_icon = get_theme_icon(SNAME("menu_highlight"));
|
||||
|
||||
// TabBar overrides.
|
||||
theme_cache.icon_separation = get_theme_constant(SNAME("icon_separation"));
|
||||
theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
|
||||
|
||||
theme_cache.tab_unselected_style = get_theme_stylebox(SNAME("tab_unselected"));
|
||||
theme_cache.tab_selected_style = get_theme_stylebox(SNAME("tab_selected"));
|
||||
theme_cache.tab_disabled_style = get_theme_stylebox(SNAME("tab_disabled"));
|
||||
|
||||
theme_cache.increment_icon = get_theme_icon(SNAME("increment"));
|
||||
theme_cache.increment_hl_icon = get_theme_icon(SNAME("increment_highlight"));
|
||||
theme_cache.decrement_icon = get_theme_icon(SNAME("decrement"));
|
||||
theme_cache.decrement_hl_icon = get_theme_icon(SNAME("decrement_highlight"));
|
||||
theme_cache.drop_mark_icon = get_theme_icon(SNAME("drop_mark"));
|
||||
theme_cache.drop_mark_color = get_theme_color(SNAME("drop_mark_color"));
|
||||
|
||||
theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
|
||||
theme_cache.font_unselected_color = get_theme_color(SNAME("font_unselected_color"));
|
||||
theme_cache.font_disabled_color = get_theme_color(SNAME("font_disabled_color"));
|
||||
theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
|
||||
|
||||
theme_cache.tab_font = get_theme_font(SNAME("font"));
|
||||
theme_cache.tab_font_size = get_theme_font_size(SNAME("font_size"));
|
||||
}
|
||||
|
||||
void TabContainer::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
@ -155,31 +187,26 @@ void TabContainer::_notification(int p_what) {
|
||||
Size2 size = get_size();
|
||||
|
||||
// Draw only the tab area if the header is hidden.
|
||||
Ref<StyleBox> panel = get_theme_stylebox(SNAME("panel"));
|
||||
if (!tabs_visible) {
|
||||
panel->draw(canvas, Rect2(0, 0, size.width, size.height));
|
||||
theme_cache.panel_style->draw(canvas, Rect2(0, 0, size.width, size.height));
|
||||
return;
|
||||
}
|
||||
|
||||
int header_height = _get_top_margin();
|
||||
|
||||
// Draw background for the tabbar.
|
||||
Ref<StyleBox> tabbar_background = get_theme_stylebox(SNAME("tabbar_background"));
|
||||
tabbar_background->draw(canvas, Rect2(0, 0, size.width, header_height));
|
||||
theme_cache.tabbar_style->draw(canvas, Rect2(0, 0, size.width, header_height));
|
||||
// Draw the background for the tab's content.
|
||||
panel->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height));
|
||||
theme_cache.panel_style->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height));
|
||||
|
||||
// Draw the popup menu.
|
||||
if (get_popup()) {
|
||||
Ref<Texture2D> menu = get_theme_icon(SNAME("menu"));
|
||||
Ref<Texture2D> menu_hl = get_theme_icon(SNAME("menu_highlight"));
|
||||
|
||||
int x = is_layout_rtl() ? 0 : get_size().width - menu->get_width();
|
||||
int x = is_layout_rtl() ? 0 : get_size().width - theme_cache.menu_icon->get_width();
|
||||
|
||||
if (menu_hovered) {
|
||||
menu_hl->draw(get_canvas_item(), Point2(x, (header_height - menu_hl->get_height()) / 2));
|
||||
theme_cache.menu_hl_icon->draw(get_canvas_item(), Point2(x, (header_height - theme_cache.menu_hl_icon->get_height()) / 2));
|
||||
} else {
|
||||
menu->draw(get_canvas_item(), Point2(x, (header_height - menu->get_height()) / 2));
|
||||
theme_cache.menu_icon->draw(get_canvas_item(), Point2(x, (header_height - theme_cache.menu_icon->get_height()) / 2));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@ -198,23 +225,27 @@ void TabContainer::_on_theme_changed() {
|
||||
return;
|
||||
}
|
||||
|
||||
tab_bar->add_theme_style_override(SNAME("tab_unselected"), get_theme_stylebox(SNAME("tab_unselected")));
|
||||
tab_bar->add_theme_style_override(SNAME("tab_selected"), get_theme_stylebox(SNAME("tab_selected")));
|
||||
tab_bar->add_theme_style_override(SNAME("tab_disabled"), get_theme_stylebox(SNAME("tab_disabled")));
|
||||
tab_bar->add_theme_icon_override(SNAME("increment"), get_theme_icon(SNAME("increment")));
|
||||
tab_bar->add_theme_icon_override(SNAME("increment_highlight"), get_theme_icon(SNAME("increment_highlight")));
|
||||
tab_bar->add_theme_icon_override(SNAME("decrement"), get_theme_icon(SNAME("decrement")));
|
||||
tab_bar->add_theme_icon_override(SNAME("decrement_highlight"), get_theme_icon(SNAME("decrement_highlight")));
|
||||
tab_bar->add_theme_icon_override(SNAME("drop_mark"), get_theme_icon(SNAME("drop_mark")));
|
||||
tab_bar->add_theme_color_override(SNAME("drop_mark_color"), get_theme_color(SNAME("drop_mark_color")));
|
||||
tab_bar->add_theme_color_override(SNAME("font_selected_color"), get_theme_color(SNAME("font_selected_color")));
|
||||
tab_bar->add_theme_color_override(SNAME("font_unselected_color"), get_theme_color(SNAME("font_unselected_color")));
|
||||
tab_bar->add_theme_color_override(SNAME("font_disabled_color"), get_theme_color(SNAME("font_disabled_color")));
|
||||
tab_bar->add_theme_color_override(SNAME("font_outline_color"), get_theme_color(SNAME("font_outline_color")));
|
||||
tab_bar->add_theme_font_override(SNAME("font"), get_theme_font(SNAME("font")));
|
||||
tab_bar->add_theme_font_size_override(SNAME("font_size"), get_theme_font_size(SNAME("font_size")));
|
||||
tab_bar->add_theme_constant_override(SNAME("h_separation"), get_theme_constant(SNAME("icon_separation")));
|
||||
tab_bar->add_theme_constant_override(SNAME("outline_size"), get_theme_constant(SNAME("outline_size")));
|
||||
tab_bar->add_theme_style_override(SNAME("tab_unselected"), theme_cache.tab_unselected_style);
|
||||
tab_bar->add_theme_style_override(SNAME("tab_selected"), theme_cache.tab_selected_style);
|
||||
tab_bar->add_theme_style_override(SNAME("tab_disabled"), theme_cache.tab_disabled_style);
|
||||
|
||||
tab_bar->add_theme_icon_override(SNAME("increment"), theme_cache.increment_icon);
|
||||
tab_bar->add_theme_icon_override(SNAME("increment_highlight"), theme_cache.increment_hl_icon);
|
||||
tab_bar->add_theme_icon_override(SNAME("decrement"), theme_cache.decrement_icon);
|
||||
tab_bar->add_theme_icon_override(SNAME("decrement_highlight"), theme_cache.decrement_hl_icon);
|
||||
tab_bar->add_theme_icon_override(SNAME("drop_mark"), theme_cache.drop_mark_icon);
|
||||
tab_bar->add_theme_color_override(SNAME("drop_mark_color"), theme_cache.drop_mark_color);
|
||||
|
||||
tab_bar->add_theme_color_override(SNAME("font_selected_color"), theme_cache.font_selected_color);
|
||||
tab_bar->add_theme_color_override(SNAME("font_unselected_color"), theme_cache.font_unselected_color);
|
||||
tab_bar->add_theme_color_override(SNAME("font_disabled_color"), theme_cache.font_disabled_color);
|
||||
tab_bar->add_theme_color_override(SNAME("font_outline_color"), theme_cache.font_outline_color);
|
||||
|
||||
tab_bar->add_theme_font_override(SNAME("font"), theme_cache.tab_font);
|
||||
tab_bar->add_theme_font_size_override(SNAME("font_size"), theme_cache.tab_font_size);
|
||||
|
||||
tab_bar->add_theme_constant_override(SNAME("h_separation"), theme_cache.icon_separation);
|
||||
tab_bar->add_theme_constant_override(SNAME("outline_size"), theme_cache.outline_size);
|
||||
|
||||
_update_margins();
|
||||
if (get_tab_count() > 0) {
|
||||
@ -228,7 +259,6 @@ void TabContainer::_on_theme_changed() {
|
||||
}
|
||||
|
||||
void TabContainer::_repaint() {
|
||||
Ref<StyleBox> sb = get_theme_stylebox(SNAME("panel"));
|
||||
Vector<Control *> controls = _get_tab_controls();
|
||||
int current = get_current_tab();
|
||||
|
||||
@ -243,10 +273,10 @@ void TabContainer::_repaint() {
|
||||
c->set_offset(SIDE_TOP, _get_top_margin());
|
||||
}
|
||||
|
||||
c->set_offset(SIDE_TOP, c->get_offset(SIDE_TOP) + sb->get_margin(SIDE_TOP));
|
||||
c->set_offset(SIDE_LEFT, c->get_offset(SIDE_LEFT) + sb->get_margin(SIDE_LEFT));
|
||||
c->set_offset(SIDE_RIGHT, c->get_offset(SIDE_RIGHT) - sb->get_margin(SIDE_RIGHT));
|
||||
c->set_offset(SIDE_BOTTOM, c->get_offset(SIDE_BOTTOM) - sb->get_margin(SIDE_BOTTOM));
|
||||
c->set_offset(SIDE_TOP, c->get_offset(SIDE_TOP) + theme_cache.panel_style->get_margin(SIDE_TOP));
|
||||
c->set_offset(SIDE_LEFT, c->get_offset(SIDE_LEFT) + theme_cache.panel_style->get_margin(SIDE_LEFT));
|
||||
c->set_offset(SIDE_RIGHT, c->get_offset(SIDE_RIGHT) - theme_cache.panel_style->get_margin(SIDE_RIGHT));
|
||||
c->set_offset(SIDE_BOTTOM, c->get_offset(SIDE_BOTTOM) - theme_cache.panel_style->get_margin(SIDE_BOTTOM));
|
||||
} else {
|
||||
c->hide();
|
||||
}
|
||||
@ -256,8 +286,7 @@ void TabContainer::_repaint() {
|
||||
}
|
||||
|
||||
void TabContainer::_update_margins() {
|
||||
int menu_width = get_theme_icon(SNAME("menu"))->get_width();
|
||||
int side_margin = get_theme_constant(SNAME("side_margin"));
|
||||
int menu_width = theme_cache.menu_icon->get_width();
|
||||
|
||||
// Directly check for validity, to avoid errors when quitting.
|
||||
bool has_popup = popup_obj_id.is_valid();
|
||||
@ -271,7 +300,7 @@ void TabContainer::_update_margins() {
|
||||
|
||||
switch (get_tab_alignment()) {
|
||||
case TabBar::ALIGNMENT_LEFT: {
|
||||
tab_bar->set_offset(SIDE_LEFT, side_margin);
|
||||
tab_bar->set_offset(SIDE_LEFT, theme_cache.side_margin);
|
||||
tab_bar->set_offset(SIDE_RIGHT, has_popup ? -menu_width : 0);
|
||||
} break;
|
||||
|
||||
@ -293,10 +322,10 @@ void TabContainer::_update_margins() {
|
||||
int total_tabs_width = last_tab_rect.position.x - first_tab_pos + last_tab_rect.size.width;
|
||||
|
||||
// Calculate if all the tabs would still fit if the margin was present.
|
||||
if (get_clip_tabs() && (tab_bar->get_offset_buttons_visible() || (get_tab_count() > 1 && (total_tabs_width + side_margin) > get_size().width))) {
|
||||
if (get_clip_tabs() && (tab_bar->get_offset_buttons_visible() || (get_tab_count() > 1 && (total_tabs_width + theme_cache.side_margin) > get_size().width))) {
|
||||
tab_bar->set_offset(SIDE_RIGHT, has_popup ? -menu_width : 0);
|
||||
} else {
|
||||
tab_bar->set_offset(SIDE_RIGHT, -side_margin);
|
||||
tab_bar->set_offset(SIDE_RIGHT, -theme_cache.side_margin);
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -798,13 +827,12 @@ Size2 TabContainer::get_minimum_size() const {
|
||||
|
||||
if (!get_clip_tabs()) {
|
||||
if (get_popup()) {
|
||||
ms.x += get_theme_icon(SNAME("menu"))->get_width();
|
||||
ms.x += theme_cache.menu_icon->get_width();
|
||||
}
|
||||
|
||||
int side_margin = get_theme_constant(SNAME("side_margin"));
|
||||
if (side_margin > 0 && get_tab_alignment() != TabBar::ALIGNMENT_CENTER &&
|
||||
if (theme_cache.side_margin > 0 && get_tab_alignment() != TabBar::ALIGNMENT_CENTER &&
|
||||
(get_tab_alignment() != TabBar::ALIGNMENT_RIGHT || !get_popup())) {
|
||||
ms.x += side_margin;
|
||||
ms.x += theme_cache.side_margin;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -824,7 +852,7 @@ Size2 TabContainer::get_minimum_size() const {
|
||||
}
|
||||
ms.y += max_control_height;
|
||||
|
||||
Size2 panel_ms = get_theme_stylebox(SNAME("panel"))->get_minimum_size();
|
||||
Size2 panel_ms = theme_cache.panel_style->get_minimum_size();
|
||||
ms.x = MAX(ms.x, panel_ms.x);
|
||||
ms.y += panel_ms.y;
|
||||
|
||||
|
@ -48,6 +48,39 @@ class TabContainer : public Container {
|
||||
bool theme_changing = false;
|
||||
Node *child_removing = nullptr;
|
||||
|
||||
struct ThemeCache {
|
||||
int side_margin = 0;
|
||||
|
||||
Ref<StyleBox> panel_style;
|
||||
Ref<StyleBox> tabbar_style;
|
||||
|
||||
Ref<Texture2D> menu_icon;
|
||||
Ref<Texture2D> menu_hl_icon;
|
||||
|
||||
// TabBar overrides.
|
||||
int icon_separation = 0;
|
||||
int outline_size = 0;
|
||||
|
||||
Ref<StyleBox> tab_unselected_style;
|
||||
Ref<StyleBox> tab_selected_style;
|
||||
Ref<StyleBox> tab_disabled_style;
|
||||
|
||||
Ref<Texture2D> increment_icon;
|
||||
Ref<Texture2D> increment_hl_icon;
|
||||
Ref<Texture2D> decrement_icon;
|
||||
Ref<Texture2D> decrement_hl_icon;
|
||||
Ref<Texture2D> drop_mark_icon;
|
||||
Color drop_mark_color;
|
||||
|
||||
Color font_selected_color;
|
||||
Color font_unselected_color;
|
||||
Color font_disabled_color;
|
||||
Color font_outline_color;
|
||||
|
||||
Ref<Font> tab_font;
|
||||
int tab_font_size;
|
||||
} theme_cache;
|
||||
|
||||
int _get_top_margin() const;
|
||||
Vector<Control *> _get_tab_controls() const;
|
||||
void _on_theme_changed();
|
||||
@ -65,6 +98,8 @@ class TabContainer : public Container {
|
||||
|
||||
protected:
|
||||
virtual void gui_input(const Ref<InputEvent> &p_event) override;
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
void _notification(int p_what);
|
||||
virtual void add_child_notify(Node *p_child) override;
|
||||
virtual void move_child_notify(Node *p_child) override;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -482,12 +482,13 @@ private:
|
||||
|
||||
void propagate_set_columns(TreeItem *p_item);
|
||||
|
||||
struct Cache {
|
||||
struct ThemeCache {
|
||||
Ref<Font> font;
|
||||
Ref<Font> tb_font;
|
||||
int font_size = 0;
|
||||
int tb_font_size = 0;
|
||||
Ref<StyleBox> bg;
|
||||
Ref<StyleBox> bg_focus;
|
||||
Ref<StyleBox> selected;
|
||||
Ref<StyleBox> selected_focus;
|
||||
Ref<StyleBox> cursor;
|
||||
@ -505,8 +506,9 @@ private:
|
||||
Ref<Texture2D> checked;
|
||||
Ref<Texture2D> unchecked;
|
||||
Ref<Texture2D> indeterminate;
|
||||
Ref<Texture2D> arrow_collapsed;
|
||||
Ref<Texture2D> arrow;
|
||||
Ref<Texture2D> arrow_collapsed;
|
||||
Ref<Texture2D> arrow_collapsed_mirrored;
|
||||
Ref<Texture2D> select_arrow;
|
||||
Ref<Texture2D> updown;
|
||||
|
||||
@ -536,7 +538,9 @@ private:
|
||||
int scroll_border = 0;
|
||||
int scroll_speed = 0;
|
||||
int font_outline_size = 0;
|
||||
} theme_cache;
|
||||
|
||||
struct Cache {
|
||||
enum ClickType {
|
||||
CLICK_NONE,
|
||||
CLICK_TITLE,
|
||||
@ -559,7 +563,6 @@ private:
|
||||
Point2i text_editor_position;
|
||||
|
||||
bool rtl = false;
|
||||
|
||||
} cache;
|
||||
|
||||
int _get_title_button_height() const;
|
||||
@ -572,7 +575,6 @@ private:
|
||||
bool v_scroll_enabled = true;
|
||||
|
||||
Size2 get_internal_min_size() const;
|
||||
void update_cache();
|
||||
void update_scrollbars();
|
||||
|
||||
Rect2 search_item_rect(TreeItem *p_from, TreeItem *p_item);
|
||||
@ -620,6 +622,8 @@ private:
|
||||
bool _scroll(bool p_horizontal, float p_pages);
|
||||
|
||||
protected:
|
||||
virtual void _update_theme_item_cache() override;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user