This commit is contained in:
firestarsdog
2026-08-26 09:46:20 -04:00
parent b2885f9f89
commit 8d246f3c0d
2 changed files with 95 additions and 66 deletions
@@ -435,10 +435,10 @@ _SOURCE_READABLE_ICON_GAP = 8.0
_SOURCE_LABEL_FONT = 28
_SOURCE_MIN_LABEL_FONT = 18
_SOURCE_VALUE_FONT = 38
_SOURCE_DENSE_VALUE_FONT = 54
_SOURCE_DENSE_FOOTER_VALUE_FONT = 48
_SOURCE_DENSE_ICON_SIZE = 40
_SOURCE_DENSE_SMALL_ICON_SIZE = 34
_SOURCE_DENSE_VALUE_FONT = 38
_SOURCE_DENSE_FOOTER_VALUE_FONT = 36
_SOURCE_DENSE_ICON_SIZE = 32
_SOURCE_DENSE_SMALL_ICON_SIZE = 28
_SOURCE_DENSE_GAP = 8.0
_SOURCE_DENSE_FOOTER_HEIGHT = 60.0
_SOURCE_MIN_VALUE_FONT = 30
@@ -731,95 +731,130 @@ def _draw_dense_source_cell(
icon_size: float,
value_font: int,
draw_chrome: bool,
footer_label: str | None = None,
font_semi = None,
) -> None:
if item.is_active and draw_chrome:
active_rect = rl.Rectangle(cell.x + 3, cell.y + 3, cell.width - 6, cell.height - 6)
rl.draw_rectangle_rounded_lines_ex(
active_rect,
roundness_for(active_rect, 14),
CONTROL_SEGMENTS,
2,
_color_with_alpha(_SOURCE_ACTIVE_BAR, alpha),
)
is_active = item.is_active
if draw_chrome:
if is_active:
rl.draw_rectangle_rounded(cell, 0.30, 8, _color_with_alpha(rl.Color(255, 255, 255, 28), alpha))
rl.draw_rectangle_rounded_lines_ex(cell, 0.30, 8, 1.0, _color_with_alpha(rl.Color(255, 255, 255, 90), alpha))
bar_h = max(16.0, cell.height - 20.0)
bar_r = rl.Rectangle(cell.x + 4.0, round(cell.y + (cell.height - bar_h) / 2), 4.0, round(bar_h))
rl.draw_rectangle_rounded(bar_r, 0.5, 4, _color_with_alpha(_SOURCE_ACTIVE_BAR, alpha))
else:
rl.draw_rectangle_rounded(cell, 0.30, 8, _color_with_alpha(rl.Color(255, 255, 255, 10), alpha))
value_text = source_value_text(item.value)
icon_size, value_font, fit_size = _fit_dense_group(font_bold, value_text, cell, icon_size, value_font)
value_size = measure_text_cached(font_bold, value_text, value_font)
group_width = icon_size + _SOURCE_DENSE_GAP + fit_size.x
group_left = cell.x + (cell.width - group_width) / 2
icon_y = cell.y + (cell.height - icon_size) / 2
text_y = cell.y + (cell.height - value_size.y) / 2
if footer_label and font_semi:
label_text = tr(footer_label)
label_font = 24
label_size = measure_text_cached(font_semi, label_text, label_font)
total_group_w = icon_size + _SOURCE_DENSE_GAP + label_size.x + 16.0 + fit_size.x
group_left = cell.x + (cell.width - total_group_w) / 2
if is_active:
group_left += 2.0
icon_y = cell.y + (cell.height - icon_size) / 2
label_y = cell.y + (cell.height - label_size.y) / 2
text_y = cell.y + (cell.height - value_size.y) / 2
_draw_source_icon(item.icon_key, group_left, round(icon_y), icon_size, _source_icon_color(item, alpha))
rl.draw_text_ex(
font_bold,
value_text,
rl.Vector2(
round(group_left + icon_size + _SOURCE_DENSE_GAP + (fit_size.x - value_size.x) / 2),
round(text_y),
),
value_font,
0,
_source_text_color(item, alpha),
)
_draw_source_icon(item.icon_key, round(group_left), round(icon_y), icon_size, _source_icon_color(item, alpha))
rl.draw_text_ex(
font_semi,
label_text,
rl.Vector2(round(group_left + icon_size + _SOURCE_DENSE_GAP), round(label_y)),
label_font,
0,
_source_text_color(item, alpha),
)
rl.draw_text_ex(
font_bold,
value_text,
rl.Vector2(
round(group_left + icon_size + _SOURCE_DENSE_GAP + label_size.x + 16.0 + (fit_size.x - value_size.x) / 2),
round(text_y),
),
value_font,
0,
_source_text_color(item, alpha),
)
else:
total_group_w = icon_size + _SOURCE_DENSE_GAP + fit_size.x
group_left = cell.x + (cell.width - total_group_w) / 2
if is_active:
group_left += 2.0
icon_y = cell.y + (cell.height - icon_size) / 2
text_y = cell.y + (cell.height - value_size.y) / 2
_draw_source_icon(item.icon_key, round(group_left), round(icon_y), icon_size, _source_icon_color(item, alpha))
rl.draw_text_ex(
font_bold,
value_text,
rl.Vector2(
round(group_left + icon_size + _SOURCE_DENSE_GAP + (fit_size.x - value_size.x) / 2),
round(text_y),
),
value_font,
0,
_source_text_color(item, alpha),
)
def _draw_dense_sources(model: SourceBubbleModel, panel_rect: rl.Rectangle, alpha: int, font_bold, *, draw_chrome: bool) -> None:
content_left = panel_rect.x + _SOURCE_PANEL_PAD_X
content_top = panel_rect.y + _SOURCE_PANEL_PAD_Y
content_width = panel_rect.width - 2 * _SOURCE_PANEL_PAD_X
content_height = panel_rect.height - 2 * _SOURCE_PANEL_PAD_Y
divider_color = _color_with_alpha(_SOURCE_DIVIDER, alpha)
def _draw_dense_sources(model: SourceBubbleModel, panel_rect: rl.Rectangle, alpha: int, font_semi, font_bold, *, draw_chrome: bool) -> None:
pad = 8.0
gap = 6.0
content_w = panel_rect.width - 2 * pad
content_h = panel_rect.height - 2 * pad
if len(model.items) == 5:
footer_height = min(_SOURCE_DENSE_FOOTER_HEIGHT, content_height * 0.30)
grid_height = content_height - footer_height - 1
cell_width = content_width / 2
cell_height = grid_height / 2
footer_h = min(44.0, content_h * 0.28)
grid_h = content_h - footer_h - gap
cell_w = (content_w - gap) / 2
cell_h = (grid_h - gap) / 2
for index, item in enumerate(model.items[:4]):
row, column = divmod(index, 2)
_draw_dense_source_cell(
item,
rl.Rectangle(content_left + column * cell_width, content_top + row * cell_height,
cell_width, cell_height),
rl.Rectangle(
panel_rect.x + pad + column * (cell_w + gap),
panel_rect.y + pad + row * (cell_h + gap),
cell_w,
cell_h,
),
alpha,
font_bold,
icon_size=_SOURCE_DENSE_SMALL_ICON_SIZE,
value_font=_SOURCE_DENSE_FOOTER_VALUE_FONT,
draw_chrome=draw_chrome,
)
if draw_chrome:
rl.draw_line_ex(
rl.Vector2(content_left, round(content_top + grid_height)),
rl.Vector2(content_left + content_width, round(content_top + grid_height)),
1,
divider_color,
)
_draw_dense_source_cell(
model.items[4],
rl.Rectangle(content_left, content_top + grid_height + 1, content_width, footer_height),
rl.Rectangle(panel_rect.x + pad, panel_rect.y + pad + grid_h + gap, content_w, footer_h),
alpha,
font_bold,
icon_size=_SOURCE_DENSE_SMALL_ICON_SIZE,
value_font=_SOURCE_DENSE_FOOTER_VALUE_FONT,
draw_chrome=draw_chrome,
footer_label=model.items[4].label,
font_semi=font_semi,
)
if draw_chrome:
rl.draw_line_ex(rl.Vector2(round(content_left + cell_width), content_top),
rl.Vector2(round(content_left + cell_width), content_top + grid_height), 1, divider_color)
rl.draw_line_ex(rl.Vector2(content_left, round(content_top + cell_height)),
rl.Vector2(content_left + content_width, round(content_top + cell_height)), 1, divider_color)
return
cell_width = content_width / 2
cell_height = content_height / 2
cell_w = (content_w - gap) / 2
cell_h = (content_h - gap) / 2
for index, item in enumerate(model.items):
row, column = divmod(index, 2)
_draw_dense_source_cell(
item,
rl.Rectangle(content_left + column * cell_width, content_top + row * cell_height,
cell_width, cell_height),
rl.Rectangle(
panel_rect.x + pad + column * (cell_w + gap),
panel_rect.y + pad + row * (cell_h + gap),
cell_w,
cell_h,
),
alpha,
font_bold,
icon_size=_SOURCE_DENSE_ICON_SIZE,
@@ -827,12 +862,6 @@ def _draw_dense_sources(model: SourceBubbleModel, panel_rect: rl.Rectangle, alph
draw_chrome=draw_chrome,
)
if draw_chrome:
rl.draw_line_ex(rl.Vector2(round(content_left + cell_width), content_top),
rl.Vector2(round(content_left + cell_width), content_top + content_height), 1, divider_color)
rl.draw_line_ex(rl.Vector2(content_left, round(content_top + cell_height)),
rl.Vector2(content_left + content_width, round(content_top + cell_height)), 1, divider_color)
def _draw_source_bubble_content(
model: SourceBubbleModel,
@@ -848,7 +877,7 @@ def _draw_source_bubble_content(
if model.mode == "empty":
_draw_sources_bubble_empty_state(panel_rect, model.empty_reason or "No data", alpha, font_semi)
elif model.mode == "dense":
_draw_dense_sources(model, panel_rect, alpha, font_bold, draw_chrome=draw_chrome)
_draw_dense_sources(model, panel_rect, alpha, font_semi, font_bold, draw_chrome=draw_chrome)
else:
_draw_readable_sources(model, panel_rect, alpha, font_semi, font_bold, draw_chrome=draw_chrome)
@@ -92,7 +92,7 @@ def test_dense_source_bubble_uses_distinct_icons_and_no_source_names(monkeypatch
slc._draw_sources_bubble(state, slc.rl.Rectangle(0, 0, 176, 196))
assert text_calls == ["45", "30", "50", "35", "20"]
assert text_calls == ["45", "30", "50", "35", "Next", "20"]
assert icon_calls == ["dashboard", "map", "camera", "navigation", "next"]