Graphic Attributes: faster view, fills on object layer, dock on first show

- The palette view looks fills up through an index of associative fills
  that is rebuilt only when the scene's geometry epoch changes, instead
  of scanning the drawing twice per frame. The gradient previews are
  cached and rebuilt only when the gradient changes.
- New fills go to the layer of the filled object. A checkbox in the
  palette menu ("Create fills on the current layer") restores the HATCH
  behaviour and is saved in the config. Objects on locked layers are
  skipped with a message.
- The palette is no longer part of the default dock layout; it is docked
  below Properties the first time it is shown and keeps a place the user
  chose. The original dock test is restored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VgkJN8DEojuPTumAXLHotu
This commit is contained in:
Claude committed 2026-10-07 17:45:38 +00:00
1 parent 3c859c6b0e
commit 119131ee10
7 files changed
+326 -86

No files matched your search

+25 -8
View File
@@ -27,8 +27,12 @@ pub struct GradientEditorState {
pub inverted: bool,
pub angle: String,
pub centered: bool,
/// Large preview, rebuilt only when a setting it depends on changes.
preview: std::cell::RefCell<Option<(PreviewKey, Option<iced::widget::image::Handle>)>>,
}
type PreviewKey = (GradientColorMode, AcadColor, AcadColor, u32, GradientKind, bool, String, bool);
#[derive(Debug, Clone)]
pub enum GradientMsg {
Open,
@@ -77,6 +81,7 @@ impl GradientEditorState {
inverted,
angle: format!("{:.1}°", hatch.gradient_color.angle.to_degrees()),
centered: hatch.gradient_color.shift.abs() < 1e-9,
preview: Default::default(),
}
}
@@ -191,18 +196,30 @@ fn preview_sized(
}
fn preview(state: &GradientEditorState) -> Element<'static, Message> {
preview_image(preview_sized(state, 370, 80))
let key: PreviewKey = (
state.color_mode,
state.color_1,
state.color_2,
state.shade_tint.to_bits(),
state.kind,
state.inverted,
state.angle.clone(),
state.centered,
);
let mut cache = state.preview.borrow_mut();
if cache.as_ref().is_none_or(|(cached, _)| *cached != key) {
*cache = Some((key, preview_sized(state, 370, 80)));
}
preview_image(cache.as_ref().and_then(|(_, handle)| handle.clone()))
}
pub(crate) fn compact_preview(hatch: &acadrust::entities::Hatch) -> Element<'static, Message> {
preview_image(preview_sized(
&GradientEditorState::from_hatch(Vec::new(), hatch),
256,
26,
))
pub(crate) fn compact_preview(
hatch: &acadrust::entities::Hatch,
) -> Option<iced::widget::image::Handle> {
preview_sized(&GradientEditorState::from_hatch(Vec::new(), hatch), 256, 26)
}
fn preview_image(handle: Option<iced::widget::image::Handle>) -> Element<'static, Message> {
pub(crate) fn preview_image(handle: Option<iced::widget::image::Handle>) -> Element<'static, Message> {
match handle {
Some(handle) => image(handle)
.width(Fill)