fix(ui): theme remaining interface text

This commit is contained in:
Hakan Seven committed 2026-07-28 12:29:31 +03:00
1 parent 28d8246c68
commit 2ac61bf99a
9 files changed
+119 -35

No files matched your search

+9
View File
@@ -81,6 +81,13 @@ impl OpenCADStudio {
pub fn view_main(&self) -> Element<'_, Message> { pub fn view_main(&self) -> Element<'_, Message> {
let i = self.active_tab; let i = self.active_tab;
let tab = &self.tabs[i]; let tab = &self.tabs[i];
let theme_text = self.active_theme.extended_palette().background.base.text;
let viewcube_text_color = [
theme_text.r,
theme_text.g,
theme_text.b,
theme_text.a,
];
let is_paper = tab.scene.current_layout != "Model"; let is_paper = tab.scene.current_layout != "Model";
// Adaptive corner widgets: the ViewCube shows only while the active // Adaptive corner widgets: the ViewCube shows only while the active
// viewport is wide enough to hold it *beside* the render-mode bar, whose // viewport is wide enough to hold it *beside* the render-mode bar, whose
@@ -137,6 +144,7 @@ impl OpenCADStudio {
&tab.scene, &tab.scene,
viewcube_visible, viewcube_visible,
tab.render_mode, tab.render_mode,
viewcube_text_color,
)) ))
.width(Fill) .width(Fill)
.height(Fill) .height(Fill)
@@ -172,6 +180,7 @@ impl OpenCADStudio {
show_viewcube, show_viewcube,
render_mode, render_mode,
idx, idx,
viewcube_text_color,
)) ))
.width(Fill) .width(Fill)
.height(Fill), .height(Fill),
+1
View File
@@ -841,6 +841,7 @@ pub(super) fn snap_override_overlay(pos: iced::Point) -> Element<'static, Messag
theme.extended_palette().primary.weak.color theme.extended_palette().primary.weak.color
)), )),
border: Border::default(), border: Border::default(),
text_color: theme.extended_palette().background.base.text,
..Default::default() ..Default::default()
}) })
.padding(2); .padding(2);
+1
View File
@@ -42,6 +42,7 @@ fn vc_btn<'a>(content: Element<'a, Message>, size: f32, msg: Message) -> Element
radius: 3.0.into(), radius: 3.0.into(),
..Default::default() ..Default::default()
}, },
text_color: theme.extended_palette().background.base.text,
..Default::default() ..Default::default()
}) })
.into() .into()
+23 -3
View File
@@ -576,6 +576,7 @@ impl ViewCubeText {
vp_w: u32, vp_w: u32,
vp_h: u32, vp_h: u32,
cube_px: u32, cube_px: u32,
text_color: [f32; 4],
) { ) {
let (vw, vh) = (vp_w as f32, vp_h as f32); let (vw, vh) = (vp_w as f32, vp_h as f32);
let cube_half = cube_px as f32 * VIEWCUBE_SCALE; let cube_half = cube_px as f32 * VIEWCUBE_SCALE;
@@ -637,7 +638,12 @@ impl ViewCubeText {
continue; continue;
} }
let alpha = ((dot - 0.12) / 0.88).clamp(0.0, 1.0); let alpha = ((dot - 0.12) / 0.88).clamp(0.0, 1.0);
let color = [1.0, 1.0, 1.0, alpha]; let color = [
text_color[0],
text_color[1],
text_color[2],
text_color[3] * alpha,
];
let u = Vec3::from(FACE_U[fi]); let u = Vec3::from(FACE_U[fi]);
let v = Vec3::from(FACE_V[fi]); let v = Vec3::from(FACE_V[fi]);
let center = face_n; // unit normal = face surface centre (distance E) let center = face_n; // unit normal = face surface centre (distance E)
@@ -714,7 +720,12 @@ impl ViewCubeText {
} else { } else {
0.5 0.5
}; };
let color = [1.0, 1.0, 1.0, alpha]; let color = [
text_color[0],
text_color[1],
text_color[2],
text_color[3] * alpha,
];
let (u0, v0, u1, v1) = glyph_uv(gi, self.atlas_w, self.atlas_h); let (u0, v0, u1, v1) = glyph_uv(gi, self.atlas_w, self.atlas_h);
let corner = |lx: f32, ly: f32| center + Vec3::X * lx + Vec3::Y * ly; let corner = |lx: f32, ly: f32| center + Vec3::X * lx + Vec3::Y * ly;
let tl = project_world(corner(-CARD_GW * 0.5, CARD_GH * 0.5)); let tl = project_world(corner(-CARD_GW * 0.5, CARD_GH * 0.5));
@@ -1232,6 +1243,7 @@ impl ViewCubePipeline {
vp_w: u32, vp_w: u32,
vp_h: u32, vp_h: u32,
hover: Option<usize>, hover: Option<usize>,
text_color: [f32; 4],
) { ) {
queue.write_buffer( queue.write_buffer(
&self.uniform_buffer, &self.uniform_buffer,
@@ -1245,7 +1257,15 @@ impl ViewCubePipeline {
)), )),
); );
self.text self.text
.update(queue, cam_rotation, compass_rotation, vp_w, vp_h, self.cube_px); .update(
queue,
cam_rotation,
compass_rotation,
vp_w,
vp_h,
self.cube_px,
text_color,
);
} }
pub fn ensure_depth_texture(&mut self, device: &wgpu::Device, size: Size<u32>) { pub fn ensure_depth_texture(&mut self, device: &wgpu::Device, size: Size<u32>) {
+9
View File
@@ -152,6 +152,8 @@ pub struct Primitive {
pub(in crate::scene) viewports: Vec<ViewportData>, pub(in crate::scene) viewports: Vec<ViewportData>,
/// Background color used to clear each viewport's MSAA buffer. /// Background color used to clear each viewport's MSAA buffer.
pub(in crate::scene) bg_color: [f32; 4], pub(in crate::scene) bg_color: [f32; 4],
/// Active Iced theme text colour for GPU-rendered ViewCube labels.
pub(in crate::scene) viewcube_text_color: [f32; 4],
/// One input-to-render sample, carried only when PERF tracing is enabled. /// One input-to-render sample, carried only when PERF tracing is enabled.
pub(in crate::scene) nav_perf: Option<NavPerfSample>, pub(in crate::scene) nav_perf: Option<NavPerfSample>,
} }
@@ -327,6 +329,7 @@ impl shader::Primitive for Primitive {
(vp.screen_rect.width * bounds.width) as u32, (vp.screen_rect.width * bounds.width) as u32,
(vp.screen_rect.height * bounds.height) as u32, (vp.screen_rect.height * bounds.height) as u32,
vp.hover_region, vp.hover_region,
self.viewcube_text_color,
); );
} }
continue; continue;
@@ -874,6 +877,7 @@ impl shader::Primitive for Primitive {
(vp.screen_rect.width * bounds.width) as u32, (vp.screen_rect.width * bounds.width) as u32,
(vp.screen_rect.height * bounds.height) as u32, (vp.screen_rect.height * bounds.height) as u32,
vp.hover_region, vp.hover_region,
self.viewcube_text_color,
); );
} }
} }
@@ -1689,6 +1693,7 @@ impl Scene {
model_render_mode: acadrust::entities::ViewportRenderMode, model_render_mode: acadrust::entities::ViewportRenderMode,
_hover_region: Option<usize>, _hover_region: Option<usize>,
show_viewcube: bool, show_viewcube: bool,
viewcube_text_color: [f32; 4],
) -> Primitive { ) -> Primitive {
let nav_build_started = iced::time::Instant::now(); let nav_build_started = iced::time::Instant::now();
let perf_nav = self.take_nav_perf(); let perf_nav = self.take_nav_perf();
@@ -1720,6 +1725,7 @@ impl Scene {
Primitive { Primitive {
viewports, viewports,
bg_color, bg_color,
viewcube_text_color,
nav_perf: perf_nav, nav_perf: perf_nav,
} }
} }
@@ -1736,6 +1742,7 @@ impl Scene {
tile_idx: usize, tile_idx: usize,
model_render_mode: acadrust::entities::ViewportRenderMode, model_render_mode: acadrust::entities::ViewportRenderMode,
show_viewcube: bool, show_viewcube: bool,
viewcube_text_color: [f32; 4],
) -> Primitive { ) -> Primitive {
let hover_region = self.viewcube_hover.get(); let hover_region = self.viewcube_hover.get();
let canvas = (bounds.width.max(1.0), bounds.height.max(1.0)); let canvas = (bounds.width.max(1.0), bounds.height.max(1.0));
@@ -1745,6 +1752,7 @@ impl Scene {
return Primitive { return Primitive {
viewports: vec![], viewports: vec![],
bg_color, bg_color,
viewcube_text_color,
nav_perf: None, nav_perf: None,
}; };
}; };
@@ -1792,6 +1800,7 @@ impl Scene {
Primitive { Primitive {
viewports, viewports,
bg_color, bg_color,
viewcube_text_color,
nav_perf: perf_nav, nav_perf: perf_nav,
} }
} }
+9
View File
@@ -23,6 +23,9 @@ pub struct ViewportPane<'a> {
/// per `pane_grid` pane, filling its own bounds). `None` → the unified /// per `pane_grid` pane, filling its own bounds). `None` → the unified
/// full-canvas path (paper layout, or the whole-canvas Model fallback). /// full-canvas path (paper layout, or the whole-canvas Model fallback).
pub pane: Option<usize>, pub pane: Option<usize>,
/// Active Iced theme text colour, forwarded to the GPU-rendered ViewCube
/// face and compass labels.
pub viewcube_text_color: [f32; 4],
} }
impl<'a> ViewportPane<'a> { impl<'a> ViewportPane<'a> {
@@ -30,12 +33,14 @@ impl<'a> ViewportPane<'a> {
scene: &'a Scene, scene: &'a Scene,
show_viewcube: bool, show_viewcube: bool,
render_mode: acadrust::entities::ViewportRenderMode, render_mode: acadrust::entities::ViewportRenderMode,
viewcube_text_color: [f32; 4],
) -> Self { ) -> Self {
Self { Self {
scene, scene,
show_viewcube, show_viewcube,
render_mode, render_mode,
pane: None, pane: None,
viewcube_text_color,
} }
} }
@@ -46,12 +51,14 @@ impl<'a> ViewportPane<'a> {
show_viewcube: bool, show_viewcube: bool,
render_mode: acadrust::entities::ViewportRenderMode, render_mode: acadrust::entities::ViewportRenderMode,
tile_idx: usize, tile_idx: usize,
viewcube_text_color: [f32; 4],
) -> Self { ) -> Self {
Self { Self {
scene, scene,
show_viewcube, show_viewcube,
render_mode, render_mode,
pane: Some(tile_idx), pane: Some(tile_idx),
viewcube_text_color,
} }
} }
} }
@@ -74,12 +81,14 @@ impl<'a, Msg: std::fmt::Debug + Clone> shader::Program<Msg> for ViewportPane<'a>
idx, idx,
self.render_mode, self.render_mode,
self.show_viewcube, self.show_viewcube,
self.viewcube_text_color,
), ),
None => self.scene.build_viewports( None => self.scene.build_viewports(
bounds, bounds,
self.render_mode, self.render_mode,
state.hover_region, state.hover_region,
self.show_viewcube, self.show_viewcube,
self.viewcube_text_color,
), ),
} }
} }
+18 -12
View File
@@ -140,6 +140,21 @@ pub fn color_selector<'a>(
}) })
} }
fn list_row_style(theme: &Theme, status: button::Status) -> button::Style {
let palette = theme.extended_palette();
let hovered = matches!(status, button::Status::Hovered);
let text_color = if hovered {
palette.background.strong.text
} else {
palette.background.base.text
};
button::Style {
background: hovered.then_some(Background::Color(palette.background.strong.color)),
text_color,
..Default::default()
}
}
/// The colour list shown inside a picker popup: named ACI colours (with /// The colour list shown inside a picker popup: named ACI colours (with
/// swatches) plus a "More…" entry that opens the full palette window. Shared by /// swatches) plus a "More…" entry that opens the full palette window. Shared by
/// `color_selector` and the ribbon's colour overlay. /// `color_selector` and the ribbon's colour overlay.
@@ -156,12 +171,7 @@ pub fn color_list<'a>(
.align_y(iced::Center), .align_y(iced::Center),
) )
.on_press(on_select(color)) .on_press(on_select(color))
.style(|theme: &Theme, status| button::Style { .style(list_row_style)
background: matches!(status, button::Status::Hovered).then_some(
Background::Color(theme.extended_palette().background.strong.color)
),
..Default::default()
})
.padding([2, 4]) .padding([2, 4])
.width(Length::Fill) .width(Length::Fill)
.into() .into()
@@ -180,12 +190,7 @@ pub fn color_list<'a>(
list = list.push( list = list.push(
button(text("More…").size(11)) button(text("More…").size(11))
.on_press(on_more) .on_press(on_more)
.style(|theme: &Theme, status| button::Style { .style(list_row_style)
background: matches!(status, button::Status::Hovered).then_some(
Background::Color(theme.extended_palette().background.strong.color)
),
..Default::default()
})
.padding([2, 4]) .padding([2, 4])
.width(Length::Fill), .width(Length::Fill),
); );
@@ -236,6 +241,7 @@ pub fn color_grid_window(on_pick: impl Fn(AcadColor) -> Message) -> Element<'sta
}, },
radius: 1.0.into(), radius: 1.0.into(),
}, },
text_color: theme.extended_palette().background.base.text,
..Default::default() ..Default::default()
}) })
.padding(0), .padding(0),
+2
View File
@@ -951,6 +951,7 @@ pub fn color_picker_dropdown<'a>(
}, },
radius: 2.0.into(), radius: 2.0.into(),
}, },
text_color: theme.extended_palette().background.base.text,
..Default::default() ..Default::default()
}) })
.padding(0), .padding(0),
@@ -1033,6 +1034,7 @@ pub fn color_picker_dropdown<'a>(
}, },
radius: 1.0.into(), radius: 1.0.into(),
}, },
text_color: theme.extended_palette().background.base.text,
..Default::default() ..Default::default()
}) })
.padding(0), .padding(0),
+47 -20
View File
@@ -475,6 +475,48 @@ impl LayerPanel {
// ── Sorting helpers ───────────────────────────────────────────────────────── // ── Sorting helpers ─────────────────────────────────────────────────────────
fn layer_cell_button_style(
theme: &Theme,
status: button::Status,
is_selected: bool,
index: usize,
) -> button::Style {
let palette = theme.extended_palette();
let highlighted = matches!(status, button::Status::Hovered);
let pair = if highlighted {
palette.background.strong
} else if is_selected {
palette.primary.weak
} else if index % 2 == 0 {
palette.background.base
} else {
palette.background.weak
};
button::Style {
background: highlighted.then_some(Background::Color(pair.color)),
text_color: pair.text,
..Default::default()
}
}
fn layer_header_button_style(theme: &Theme, status: button::Status) -> button::Style {
let palette = theme.extended_palette();
let highlighted = matches!(
status,
button::Status::Hovered | button::Status::Pressed
);
let pair = if highlighted {
palette.background.strong
} else {
palette.background.weak
};
button::Style {
background: highlighted.then_some(Background::Color(pair.color)),
text_color: pair.text,
..Default::default()
}
}
/// Packed RGB key for ordering colours deterministically by hue-ish bytes. /// Packed RGB key for ordering colours deterministically by hue-ish bytes.
fn color_sort_key(c: Color) -> u32 { fn color_sort_key(c: Color) -> u32 {
let q = |v: f32| (v.clamp(0.0, 1.0) * 255.0).round() as u32; let q = |v: f32| (v.clamp(0.0, 1.0) * 255.0).round() as u32;
@@ -502,16 +544,7 @@ fn sortable_header<'a>(
} }
button(content) button(content)
.on_press(Message::LayerSort(col)) .on_press(Message::LayerSort(col))
.style(|theme: &Theme, status| button::Style { .style(layer_header_button_style)
background: matches!(
status,
button::Status::Hovered | button::Status::Pressed
)
.then_some(Background::Color(
theme.extended_palette().background.strong.color
)),
..Default::default()
})
.padding(Padding { .padding(Padding {
top: 0.0, top: 0.0,
bottom: 0.0, bottom: 0.0,
@@ -655,11 +688,8 @@ fn layer_row<'a>(
let svg_btn = |bytes: &'static [u8], on_press: Message| -> Element<'a, Message> { let svg_btn = |bytes: &'static [u8], on_press: Message| -> Element<'a, Message> {
button(crate::ui::icons::semantic(bytes, ICON_SZ)) button(crate::ui::icons::semantic(bytes, ICON_SZ))
.on_press(on_press) .on_press(on_press)
.style(|theme: &Theme, status| button::Style { .style(move |theme: &Theme, status| {
background: matches!(status, button::Status::Hovered).then_some( layer_cell_button_style(theme, status, is_selected, index)
Background::Color(theme.extended_palette().background.strong.color)
),
..Default::default()
}) })
.padding(Padding { .padding(Padding {
top: COMBO_PAD_V, top: COMBO_PAD_V,
@@ -704,11 +734,8 @@ fn layer_row<'a>(
.size(FONT_SZ), .size(FONT_SZ),
) )
.on_press(Message::LayerRenameStart(index)) .on_press(Message::LayerRenameStart(index))
.style(|theme: &Theme, status| button::Style { .style(move |theme: &Theme, status| {
background: matches!(status, button::Status::Hovered).then_some( layer_cell_button_style(theme, status, is_selected, index)
Background::Color(theme.extended_palette().background.strong.color)
),
..Default::default()
}) })
.padding(Padding { .padding(Padding {
top: COMBO_PAD_V, top: COMBO_PAD_V,