Toolbar: Studio themes draw round colour chips with Switch Colors below (#2002)
* Toolbar: Studio themes draw large round colour chips with Switch Colors right below * Toolbar: round chips keep Default Colors, follow Tokens::round_chips, lie side by side in two columns * Theme: Solarized Dark and Adwaita use the Studio round colour chips --------- Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
parent
cc584d9aff
commit
782bcb67fa
|
|
@ -82,7 +82,8 @@ pub fn toolbar(app: &mut PhotocraftApp, ui: &mut egui::Ui) {
|
|||
let sections = visible_sections(&app.session.prefs().toolbar.hidden);
|
||||
// Two columns when the header chevron asks for them, or when one column doesn't fit.
|
||||
let slots: usize = sections.iter().map(Vec::len).sum();
|
||||
let double = app.ui.panels.toolbar_double || toolbar_needs_double(slots, sections.len(), bx, t.pro, ui.available_rect_before_wrap().height());
|
||||
let double =
|
||||
app.ui.panels.toolbar_double || toolbar_needs_double(slots, sections.len(), bx, t.pro, t.round_chips, ui.available_rect_before_wrap().height());
|
||||
let w = if double { w1 + bx + 2.0 } else { w1 };
|
||||
egui::Panel::left("toolbar").resizable(false).exact_size(w).frame(egui::Frame::NONE.fill(t.chrome).inner_margin(egui::Margin::symmetric(m, 8))).show(
|
||||
ui,
|
||||
|
|
@ -245,7 +246,7 @@ pub fn toolbar(app: &mut PhotocraftApp, ui: &mut egui::Ui) {
|
|||
let _ = crate::menus::invoke(app, &ctx, "edit.toolbar", json!({}));
|
||||
}
|
||||
ui.add_space(if t.pro { 8.0 } else { 14.0 });
|
||||
color_chips(app, ui);
|
||||
color_chips(app, ui, double);
|
||||
if t.pro {
|
||||
ui.add_space(8.0);
|
||||
let quick_mask = app.session.active().is_some_and(|s| s.doc.quick_mask.is_some());
|
||||
|
|
@ -286,13 +287,13 @@ pub fn toolbar(app: &mut PhotocraftApp, ui: &mut egui::Ui) {
|
|||
|
||||
/// Does the toolbar need two columns? Height of one column (header, tool slots, Edit Toolbar,
|
||||
/// colour chips, Quick Mask and Screen Mode) against the height the toolbar gets.
|
||||
pub fn toolbar_needs_double(slots: usize, sections: usize, bx: f32, pro: bool, avail_h: f32) -> bool {
|
||||
pub fn toolbar_needs_double(slots: usize, sections: usize, bx: f32, pro: bool, studio: bool, avail_h: f32) -> bool {
|
||||
let pitch = bx + 3.0;
|
||||
let needed = if pro {
|
||||
// margins + header + slots + "…" + gap + colour chips + gap + 2 buttons
|
||||
16.0 + 21.0 + (slots + 1) as f32 * pitch + 8.0 + chips_height(true) + 8.0 + 2.0 * pitch
|
||||
16.0 + 21.0 + (slots + 1) as f32 * pitch + 8.0 + chips_height(true, false, false) + 8.0 + 2.0 * pitch
|
||||
} else {
|
||||
16.0 + slots as f32 * pitch + sections.saturating_sub(1) as f32 * 12.0 + 14.0 + chips_height(false)
|
||||
16.0 + slots as f32 * pitch + sections.saturating_sub(1) as f32 * 12.0 + 14.0 + chips_height(false, studio, false)
|
||||
};
|
||||
needed > avail_h
|
||||
}
|
||||
|
|
@ -309,8 +310,21 @@ fn chip_metrics(pro: bool) -> (f32, f32) {
|
|||
/// Height of the default-colours and swap icons over the chips.
|
||||
const CHIP_ICON: f32 = 13.0;
|
||||
|
||||
/// Studio themes: round chip diameter and the background chip's vertical offset (points).
|
||||
const STUDIO_CHIP: (f32, f32) = (30.0, 19.0);
|
||||
/// Room under the round chips for the Default Colors and Switch Colors buttons.
|
||||
const STUDIO_ROW: f32 = 15.0;
|
||||
/// Room above the stacked round chips so Default Colors, at their top-right, clears them.
|
||||
const STUDIO_TOP: f32 = 6.0;
|
||||
|
||||
/// Height of the colour chips block.
|
||||
fn chips_height(pro: bool) -> f32 {
|
||||
fn chips_height(pro: bool, studio: bool, wide: bool) -> f32 {
|
||||
if studio && wide {
|
||||
return STUDIO_CHIP.0 + STUDIO_ROW;
|
||||
}
|
||||
if studio {
|
||||
return STUDIO_TOP + STUDIO_CHIP.0 + STUDIO_CHIP.1 + STUDIO_ROW;
|
||||
}
|
||||
let (chip, step) = chip_metrics(pro);
|
||||
CHIP_ICON + 3.0 + chip + step
|
||||
}
|
||||
|
|
@ -318,28 +332,52 @@ fn chips_height(pro: bool) -> f32 {
|
|||
/// Photoshop's foreground / background colour chips: the Default Colors (D) and Switch Colors (X)
|
||||
/// icons above them, the foreground chip over the background one, all centred in the toolbar
|
||||
/// column and kept inside it.
|
||||
fn color_chips(app: &mut PhotocraftApp, ui: &mut egui::Ui) {
|
||||
fn color_chips(app: &mut PhotocraftApp, ui: &mut egui::Ui, two_columns: bool) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let (chip, step) = chip_metrics(t.pro);
|
||||
let group = chip + step;
|
||||
// Studio themes: round chips stacked vertically, the controls below them.
|
||||
let studio = t.round_chips;
|
||||
let (chip, step) = if studio { STUDIO_CHIP } else { chip_metrics(t.pro) };
|
||||
// With two tool columns (a short window) the round chips lie side by side, which saves height.
|
||||
let wide = studio && two_columns;
|
||||
let group = if studio && !wide { chip } else { chip + step };
|
||||
let w = ui.available_width().max(group);
|
||||
let (rect, _) = ui.allocate_exact_size(vec2(w, chips_height(t.pro)), Sense::hover());
|
||||
let (rect, _) = ui.allocate_exact_size(vec2(w, chips_height(t.pro, studio, wide)), Sense::hover());
|
||||
let left = (rect.left() + (w - group) / 2.0).round();
|
||||
let fg = Rect::from_min_size(pos2(left, rect.top() + CHIP_ICON + 3.0), vec2(chip, chip));
|
||||
let bg = fg.translate(vec2(step, step));
|
||||
let (fg, bg) = if wide {
|
||||
let fg = Rect::from_min_size(pos2(left, rect.top()), vec2(chip, chip));
|
||||
(fg, fg.translate(vec2(step, 0.0)))
|
||||
} else if studio {
|
||||
let fg = Rect::from_min_size(pos2(left, rect.top() + STUDIO_TOP), vec2(chip, chip));
|
||||
(fg, fg.translate(vec2(0.0, step)))
|
||||
} else {
|
||||
let fg = Rect::from_min_size(pos2(left, rect.top() + CHIP_ICON + 3.0), vec2(chip, chip));
|
||||
(fg, fg.translate(vec2(step, step)))
|
||||
};
|
||||
let radius = t.radius_sm.min(3.0);
|
||||
let p = ui.painter();
|
||||
let frame = |r: Rect| {
|
||||
// A light line inside a dark one, so any colour reads against the toolbar.
|
||||
p.rect_stroke(r, radius, Stroke::new(1.0, t.text.gamma_multiply(0.9)), StrokeKind::Inside);
|
||||
p.rect_stroke(r, radius, Stroke::new(1.0, t.field_border), StrokeKind::Outside);
|
||||
};
|
||||
p.rect_filled(bg, radius, c32(app.session.tools.background));
|
||||
frame(bg);
|
||||
// The foreground chip sits on the background one, a toolbar-coloured gap between them.
|
||||
p.rect_filled(fg.expand(2.0), radius + 2.0, t.chrome);
|
||||
p.rect_filled(fg, radius, c32(app.session.tools.foreground));
|
||||
frame(fg);
|
||||
if studio {
|
||||
let dot = |r: Rect, color: Color32| {
|
||||
p.circle_filled(r.center(), r.width() / 2.0, color);
|
||||
// A light line inside a dark one, so any colour reads against the toolbar.
|
||||
p.circle_stroke(r.center(), r.width() / 2.0 - 0.5, Stroke::new(1.0, t.text.gamma_multiply(0.9)));
|
||||
p.circle_stroke(r.center(), r.width() / 2.0 + 0.5, Stroke::new(1.0, t.field_border));
|
||||
};
|
||||
dot(bg, c32(app.session.tools.background));
|
||||
// The foreground chip sits on the background one, a toolbar-coloured gap between them.
|
||||
p.circle_filled(fg.center(), fg.width() / 2.0 + 2.0, t.chrome);
|
||||
dot(fg, c32(app.session.tools.foreground));
|
||||
} else {
|
||||
let frame = |r: Rect| {
|
||||
// A light line inside a dark one, so any colour reads against the toolbar.
|
||||
p.rect_stroke(r, radius, Stroke::new(1.0, t.text.gamma_multiply(0.9)), StrokeKind::Inside);
|
||||
p.rect_stroke(r, radius, Stroke::new(1.0, t.field_border), StrokeKind::Outside);
|
||||
};
|
||||
p.rect_filled(bg, radius, c32(app.session.tools.background));
|
||||
frame(bg);
|
||||
p.rect_filled(fg.expand(2.0), radius + 2.0, t.chrome);
|
||||
p.rect_filled(fg, radius, c32(app.session.tools.foreground));
|
||||
frame(fg);
|
||||
}
|
||||
// Photoshop: clicking a chip opens the Color Picker for that colour.
|
||||
let bg_resp = ui.interact(bg, ui.id().with("bgchip"), Sense::click());
|
||||
let fg_resp = ui.interact(fg, ui.id().with("fgchip"), Sense::click());
|
||||
|
|
@ -349,47 +387,96 @@ fn color_chips(app: &mut PhotocraftApp, ui: &mut egui::Ui) {
|
|||
crate::color_picker_ui::open(app, "background");
|
||||
}
|
||||
// Default Colors at the left, Switch Colors at the right, over the chips.
|
||||
let icon = |x: f32| Rect::from_min_size(pos2(x, rect.top()), vec2(CHIP_ICON, CHIP_ICON));
|
||||
let (dr, sr) = (icon(left), icon(left + group - CHIP_ICON));
|
||||
let d = ui.interact(dr, ui.id().with("default-colors"), Sense::click());
|
||||
let (dr, sr) = if studio {
|
||||
// Switch Colors is a curve right under the chips, centred on them so its heads touch
|
||||
// them. Default Colors never moves it: at the left edge beside it when the chips lie side
|
||||
// by side, at the block's top-right corner when they are stacked.
|
||||
let (cx, row) = ((fg.center().x + bg.center().x) / 2.0, fg.bottom().max(bg.bottom()) + 3.5);
|
||||
let default = if wide {
|
||||
Rect::from_center_size(pos2(rect.left() + CHIP_ICON / 2.0, row), vec2(CHIP_ICON, CHIP_ICON))
|
||||
} else {
|
||||
// Just high enough that its bottom-left corner clears the foreground chip's outline.
|
||||
let x = rect.right() - CHIP_ICON;
|
||||
let (dx, r) = ((x - fg.center().x).max(0.0), fg.width() / 2.0 + 1.0);
|
||||
let clear = if dx < r { (r * r - dx * dx).sqrt() } else { 0.0 };
|
||||
Rect::from_min_size(pos2(x, fg.center().y - clear - CHIP_ICON), vec2(CHIP_ICON, CHIP_ICON))
|
||||
};
|
||||
(Some(default), Rect::from_center_size(pos2(cx, row), vec2(20.0, 14.0)))
|
||||
} else {
|
||||
let icon = |x: f32| Rect::from_min_size(pos2(x, rect.top()), vec2(CHIP_ICON, CHIP_ICON));
|
||||
(Some(icon(left)), icon(left + group - CHIP_ICON))
|
||||
};
|
||||
let d = dr.map(|dr| ui.interact(dr, ui.id().with("default-colors"), Sense::click()));
|
||||
let s = ui.interact(sr, ui.id().with("swap-colors"), Sense::click());
|
||||
let p = ui.painter();
|
||||
for (r, resp) in [(dr, &d), (sr, &s)] {
|
||||
if resp.hovered() {
|
||||
for (r, resp) in dr.into_iter().zip(d.iter()).chain([(sr, &s)]) {
|
||||
if resp.hovered() && !studio {
|
||||
p.rect_filled(r.expand(2.0), radius, t.hover);
|
||||
}
|
||||
}
|
||||
let ink = |resp: &egui::Response| if resp.hovered() { t.text } else { t.icon };
|
||||
if studio {
|
||||
// Switch Colors: a shallow curve hugging the bottom chip, with a filled head at each end.
|
||||
// It glows on hover instead of getting a button box.
|
||||
let hot = s.hovered();
|
||||
let stroke = Stroke::new(1.5, ink(&s));
|
||||
let (c, rad) = (pos2(sr.center().x, sr.center().y - 5.0), 9.0);
|
||||
let (from, to) = (0.45, std::f32::consts::PI - 0.45);
|
||||
let arc: Vec<_> = (0..=12)
|
||||
.map(|i| {
|
||||
let a = from + (to - from) * i as f32 / 12.0;
|
||||
c + vec2(rad * a.cos(), rad * a.sin())
|
||||
})
|
||||
.collect();
|
||||
if hot {
|
||||
p.add(egui::Shape::line(arc.clone(), Stroke::new(5.0, t.text.gamma_multiply(0.18))));
|
||||
}
|
||||
let ends = [(arc[0], from, -1.0_f32), (arc[arc.len() - 1], to, 1.0)];
|
||||
p.add(egui::Shape::line(arc, stroke));
|
||||
// Each head points along the curve, away from its middle.
|
||||
for (end, a, sign) in ends {
|
||||
let dir = vec2(-a.sin(), a.cos()) * sign;
|
||||
let side = vec2(-dir.y, dir.x);
|
||||
let tip = end + dir * 2.5;
|
||||
let base = tip - dir * 5.0;
|
||||
p.add(egui::Shape::convex_polygon(vec![tip, base + side * 3.0, base - side * 3.0], ink(&s), Stroke::NONE));
|
||||
}
|
||||
} else {
|
||||
// Switch Colors: a quarter-circle arrow with a head at each end.
|
||||
let stroke = Stroke::new(1.3, ink(&s));
|
||||
let (c, rad) = (pos2(sr.left() + 2.0, sr.bottom() - 1.0), sr.width() - 4.0);
|
||||
let arc: Vec<_> = (0..=8)
|
||||
.map(|i| {
|
||||
let a = std::f32::consts::FRAC_PI_2 * i as f32 / 8.0;
|
||||
c + vec2(rad * a.sin(), -rad * a.cos())
|
||||
})
|
||||
.collect();
|
||||
let (start, end) = (arc[0], arc[arc.len() - 1]);
|
||||
p.add(egui::Shape::line(arc, stroke));
|
||||
let head = 3.0;
|
||||
p.line_segment([start, start + vec2(head, -head)], stroke);
|
||||
p.line_segment([start, start + vec2(head, head)], stroke);
|
||||
p.line_segment([end, end + vec2(-head, -head)], stroke);
|
||||
p.line_segment([end, end + vec2(head, -head)], stroke);
|
||||
}
|
||||
// Default Colors: a small black chip over a small white one.
|
||||
let small = 7.0;
|
||||
let (b, w) = (Rect::from_min_size(dr.min + vec2(1.0, 1.0), vec2(small, small)), Rect::from_min_size(dr.min + vec2(5.0, 5.0), vec2(small, small)));
|
||||
p.rect_filled(w, 1.0, Color32::WHITE);
|
||||
p.rect_stroke(w, 1.0, Stroke::new(1.0, ink(&d)), StrokeKind::Inside);
|
||||
p.rect_filled(b.expand(1.0), 1.5, t.chrome);
|
||||
p.rect_filled(b, 1.0, Color32::BLACK);
|
||||
p.rect_stroke(b, 1.0, Stroke::new(1.0, ink(&d)), StrokeKind::Inside);
|
||||
// Switch Colors: a quarter-circle arrow with a head at each end.
|
||||
let stroke = Stroke::new(1.3, ink(&s));
|
||||
let (c, rad) = (pos2(sr.left() + 2.0, sr.bottom() - 1.0), sr.width() - 4.0);
|
||||
let arc: Vec<_> = (0..=8)
|
||||
.map(|i| {
|
||||
let a = std::f32::consts::FRAC_PI_2 * i as f32 / 8.0;
|
||||
c + vec2(rad * a.sin(), -rad * a.cos())
|
||||
})
|
||||
.collect();
|
||||
let (start, end) = (arc[0], arc[arc.len() - 1]);
|
||||
p.add(egui::Shape::line(arc, stroke));
|
||||
let head = 3.0;
|
||||
p.line_segment([start, start + vec2(head, -head)], stroke);
|
||||
p.line_segment([start, start + vec2(head, head)], stroke);
|
||||
p.line_segment([end, end + vec2(-head, -head)], stroke);
|
||||
p.line_segment([end, end + vec2(head, -head)], stroke);
|
||||
d.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, tl!("Default colours (D)")));
|
||||
if let (Some(dr), Some(d)) = (dr, d.as_ref()) {
|
||||
let small = 7.0;
|
||||
let (b, w) = (Rect::from_min_size(dr.min + vec2(1.0, 1.0), vec2(small, small)), Rect::from_min_size(dr.min + vec2(5.0, 5.0), vec2(small, small)));
|
||||
p.rect_filled(w, 1.0, Color32::WHITE);
|
||||
p.rect_stroke(w, 1.0, Stroke::new(1.0, ink(d)), StrokeKind::Inside);
|
||||
p.rect_filled(b.expand(1.0), 1.5, t.chrome);
|
||||
p.rect_filled(b, 1.0, Color32::BLACK);
|
||||
p.rect_stroke(b, 1.0, Stroke::new(1.0, ink(d)), StrokeKind::Inside);
|
||||
}
|
||||
if let Some(d) = &d {
|
||||
d.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, tl!("Default colours (D)")));
|
||||
}
|
||||
s.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, tl!("Swap colours (X)")));
|
||||
if s.on_hover_text(tl!("Swap colours (X)")).clicked() {
|
||||
let _ = app.run("tools.swapColors", json!({}));
|
||||
}
|
||||
if d.on_hover_text(tl!("Default colours (D)")).clicked() {
|
||||
if d.is_some_and(|d| d.on_hover_text(tl!("Default colours (D)")).clicked()) {
|
||||
let _ = app.run("tools.defaultColors", json!({}));
|
||||
}
|
||||
}
|
||||
|
|
@ -3162,6 +3249,48 @@ mod color_tests {
|
|||
assert_eq!(srgb_bytes(h.state().session.tools.foreground), [0xff, 0x80, 0x00]);
|
||||
}
|
||||
|
||||
/// Themes with `round_chips` (Studio) draw round chips, stacked or side by side in two tool
|
||||
/// columns, with Switch Colors right under them and Default Colors at the top-right corner
|
||||
/// (stacked) or the left edge (side by side); both buttons work in either layout.
|
||||
#[test]
|
||||
fn studio_color_chips_keep_default_and_swap_buttons_below() {
|
||||
use egui_kittest::kittest::Queryable;
|
||||
for (kind, two_columns) in [
|
||||
(crate::theme::ThemeKind::Studio, false),
|
||||
(crate::theme::ThemeKind::StudioLight, false),
|
||||
(crate::theme::ThemeKind::Studio, true),
|
||||
(crate::theme::ThemeKind::StudioLight, true),
|
||||
] {
|
||||
let mut app = PhotocraftApp::new(photocraft_engine::Session::new(), crate::Services::default());
|
||||
app.session.tools.foreground = [1.0, 0.0, 0.0, 1.0];
|
||||
app.session.tools.background = [0.0, 0.0, 1.0, 1.0];
|
||||
let mut h = egui_kittest::Harness::builder().with_size(vec2(80.0, 120.0)).build_ui_state(|ui, app: &mut PhotocraftApp| color_chips(app, ui, two_columns), app);
|
||||
PhotocraftApp::setup_context(&h.ctx, kind);
|
||||
h.run_steps(2);
|
||||
h.get_by_label("Swap colours (X)").click();
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().session.tools.foreground, [0.0, 0.0, 1.0, 1.0], "{kind:?}");
|
||||
assert_eq!(h.state().session.tools.background, [1.0, 0.0, 0.0, 1.0], "{kind:?}");
|
||||
h.get_by_label("Default colours (D)").click();
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().session.tools.foreground, [0.0, 0.0, 0.0, 1.0], "{kind:?}");
|
||||
assert_eq!(h.state().session.tools.background, [1.0, 1.0, 1.0, 1.0], "{kind:?}");
|
||||
}
|
||||
}
|
||||
|
||||
/// The Studio layout (chips stacked, icons below) fits the height the toolbar reserves for
|
||||
/// the chips, so the two-column check does not change with the theme.
|
||||
#[test]
|
||||
fn studio_color_chips_fit_the_reserved_height() {
|
||||
// Chips, then the row holding the Switch Colors curve.
|
||||
assert!(STUDIO_CHIP.0 + STUDIO_CHIP.1 + 8.0 + 4.0 <= chips_height(false, true, false));
|
||||
// Side by side: the chips plus the same row, and shorter than stacked.
|
||||
assert!(STUDIO_CHIP.0 + 8.0 + 4.0 <= chips_height(false, true, true));
|
||||
assert!(chips_height(false, true, true) < chips_height(false, true, false));
|
||||
// The Studio block is taller than Photoshop's, and the two-column check knows it.
|
||||
assert!(chips_height(false, true, false) > chips_height(false, false, false));
|
||||
}
|
||||
|
||||
/// An incomplete entry never changes the colour and the field snaps back when focus leaves.
|
||||
#[test]
|
||||
fn color_panel_hex_field_ignores_partial_input() {
|
||||
|
|
|
|||
|
|
@ -133,6 +133,8 @@ pub struct Tokens {
|
|||
pub bevel: bool,
|
||||
/// Pro (Photoshop-grammar) layout: tab strips, flat panels, checkboxes, pill buttons.
|
||||
pub pro: bool,
|
||||
/// Toolbar colour chips are large and round, stacked, with the colour buttons below (Studio).
|
||||
pub round_chips: bool,
|
||||
/// Panel tab-strip background (Pro).
|
||||
pub tab_strip: Color32,
|
||||
/// Selected list row (layers, history).
|
||||
|
|
@ -208,6 +210,7 @@ impl Tokens {
|
|||
radius_lg: 6.0,
|
||||
bevel: false,
|
||||
pro: true,
|
||||
round_chips: false,
|
||||
tab_strip: Color32::from_rgb(38, 38, 38),
|
||||
row_selected: Color32::from_rgb(82, 82, 82),
|
||||
histogram_bg: Color32::from_rgb(40, 40, 40),
|
||||
|
|
@ -247,6 +250,7 @@ impl Tokens {
|
|||
radius_lg: 12.0,
|
||||
bevel: false,
|
||||
pro: false,
|
||||
round_chips: true,
|
||||
tab_strip: Color32::TRANSPARENT,
|
||||
row_selected: Color32::TRANSPARENT,
|
||||
histogram_bg: Color32::from_rgb(14, 14, 15),
|
||||
|
|
@ -286,6 +290,7 @@ impl Tokens {
|
|||
radius_lg: 12.0,
|
||||
bevel: false,
|
||||
pro: false,
|
||||
round_chips: true,
|
||||
tab_strip: Color32::TRANSPARENT,
|
||||
row_selected: Color32::TRANSPARENT,
|
||||
histogram_bg: Color32::from_gray(40),
|
||||
|
|
@ -325,6 +330,7 @@ impl Tokens {
|
|||
radius_lg: 0.0,
|
||||
bevel: true,
|
||||
pro: false,
|
||||
round_chips: false,
|
||||
tab_strip: Color32::from_rgb(212, 208, 200),
|
||||
row_selected: Color32::from_rgb(10, 36, 106),
|
||||
histogram_bg: Color32::from_gray(40),
|
||||
|
|
@ -367,6 +373,7 @@ impl Tokens {
|
|||
radius_lg: 12.0,
|
||||
bevel: false,
|
||||
pro: false,
|
||||
round_chips: true,
|
||||
tab_strip: Color32::TRANSPARENT,
|
||||
row_selected: Color32::TRANSPARENT,
|
||||
histogram_bg: Color32::from_gray(40),
|
||||
|
|
@ -406,6 +413,7 @@ impl Tokens {
|
|||
radius_lg: 12.0,
|
||||
bevel: false,
|
||||
pro: false,
|
||||
round_chips: true,
|
||||
tab_strip: Color32::TRANSPARENT,
|
||||
row_selected: Color32::TRANSPARENT,
|
||||
histogram_bg: Color32::from_rgb(29, 29, 32),
|
||||
|
|
@ -448,6 +456,7 @@ impl Tokens {
|
|||
radius_lg: 12.0,
|
||||
bevel: false,
|
||||
pro: false,
|
||||
round_chips: true,
|
||||
tab_strip: Color32::TRANSPARENT,
|
||||
row_selected: Color32::TRANSPARENT,
|
||||
histogram_bg: Color32::from_rgb(0, 43, 54),
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
Switch themes with the sun icon, Window → Theme, or `ui.set {"theme":"classic"}` over the control channel.
|
||||
|
||||
The toolbar's foreground and background colour chips follow the `Tokens::round_chips` flag. Pro and Classic leave it off and draw Photoshop's overlapping squares with Default Colors and Switch Colors above them. Studio, Studio Light, Solarized Dark, Adwaita and Adwaita Dark (the Studio-layout themes) turn it on and draw large round chips with a curved Switch Colors arrow centred right under them, its heads touching the chips: stacked vertically in one tool column, with Default Colors at their top-right, and side by side in two tool columns, with Default Colors at the toolbar's left edge. Another non-Pro theme can opt in by setting the flag.
|
||||
|
||||
## Rules
|
||||
|
||||
- **Colours and radii come from tokens.** Read them with `Tokens::get(ctx)`; never hard-code a colour in a widget.
|
||||
|
|
|
|||
Loading…
Reference in New Issue