forked from 1b-agent/opencadstudio-upstream
Properties: open a dropdown only on the surface that asked (#1766)
The docked panel and Quick Properties render the same rows from one state, so a picked colour opened both dropdowns and each swallowed the other's click. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1037be2d53
commit
a156a63edd
3 files changed
+62
-18
No files matched your search
@@ -3625,6 +3625,8 @@ pub enum Message {
|
|||||||
PropPointerPressed,
|
PropPointerPressed,
|
||||||
/// Toggle the inline color picker dropdown open/closed.
|
/// Toggle the inline color picker dropdown open/closed.
|
||||||
PropColorPickerToggle,
|
PropColorPickerToggle,
|
||||||
|
/// A Properties dropdown toggle and whether Quick Properties sent it.
|
||||||
|
PropPickerSurface(bool, Box<Message>),
|
||||||
/// Toggle the MTEXT background-colour picker dropdown open/closed.
|
/// Toggle the MTEXT background-colour picker dropdown open/closed.
|
||||||
PropBgColorPickerToggle,
|
PropBgColorPickerToggle,
|
||||||
/// User picked an MTEXT background fill colour — sets `background_color`
|
/// User picked an MTEXT background fill colour — sets `background_color`
|
||||||
|
|||||||
@@ -7856,6 +7856,13 @@ impl OpenCADStudio {
|
|||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Message::PropPickerSurface(quick, message) => {
|
||||||
|
let task = self.update(*message);
|
||||||
|
let i = self.active_tab;
|
||||||
|
self.tabs[i].properties.picker_in_quick = quick;
|
||||||
|
task
|
||||||
|
}
|
||||||
|
|
||||||
Message::PropColorPickerToggle => {
|
Message::PropColorPickerToggle => {
|
||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
self.tabs[i].properties.color_picker_open =
|
self.tabs[i].properties.color_picker_open =
|
||||||
|
|||||||
+53
-18
@@ -621,6 +621,12 @@ pub struct PropertiesPanel {
|
|||||||
pub collapsed_sections: HashSet<String>,
|
pub collapsed_sections: HashSet<String>,
|
||||||
/// Whether the editable-dropdown (block Name) option list is open.
|
/// Whether the editable-dropdown (block Name) option list is open.
|
||||||
pub edit_choice_open: bool,
|
pub edit_choice_open: bool,
|
||||||
|
/// The open dropdown belongs to Quick Properties, not the docked panel:
|
||||||
|
/// both render these rows, and two open copies swallow each other's
|
||||||
|
/// clicks (#1766).
|
||||||
|
pub picker_in_quick: bool,
|
||||||
|
/// Set while `quick_view` builds its rows.
|
||||||
|
pub rendering_quick: std::cell::Cell<bool>,
|
||||||
/// Field key of the value row currently being edited, or `None`. Marked when
|
/// Field key of the value row currently being edited, or `None`. Marked when
|
||||||
/// the user focuses an editable value field and cleared on commit / when the
|
/// the user focuses an editable value field and cleared on commit / when the
|
||||||
/// selection changes, so the active row can be highlighted. Geometry fields
|
/// selection changes, so the active row can be highlighted. Geometry fields
|
||||||
@@ -659,6 +665,8 @@ impl Default for PropertiesPanel {
|
|||||||
expanded_groups: HashSet::default(),
|
expanded_groups: HashSet::default(),
|
||||||
collapsed_sections: HashSet::default(),
|
collapsed_sections: HashSet::default(),
|
||||||
edit_choice_open: false,
|
edit_choice_open: false,
|
||||||
|
picker_in_quick: false,
|
||||||
|
rendering_quick: std::cell::Cell::new(false),
|
||||||
active_field: None,
|
active_field: None,
|
||||||
field_key_by_id: HashMap::default(),
|
field_key_by_id: HashMap::default(),
|
||||||
}
|
}
|
||||||
@@ -680,6 +688,11 @@ impl PropertiesPanel {
|
|||||||
self.field_key_by_id.get(id).cloned()
|
self.field_key_by_id.get(id).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the open dropdown belongs to the surface being built.
|
||||||
|
fn picker_here(&self) -> bool {
|
||||||
|
self.picker_in_quick == self.rendering_quick.get()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn selected_handles(&self) -> Vec<Handle> {
|
pub fn selected_handles(&self) -> Vec<Handle> {
|
||||||
self.selected_group
|
self.selected_group
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -744,11 +757,13 @@ impl PropertiesPanel {
|
|||||||
for section in &self.sections {
|
for section in &self.sections {
|
||||||
col = col.push(self.render_section(section));
|
col = col.push(self.render_section(section));
|
||||||
}
|
}
|
||||||
scrollable(col.width(Length::Fill))
|
Element::from(
|
||||||
.spacing(8)
|
scrollable(col.width(Length::Fill))
|
||||||
.width(Length::Fill)
|
.spacing(8)
|
||||||
.height(Length::Fill)
|
.width(Length::Fill)
|
||||||
.into()
|
.height(Length::Fill),
|
||||||
|
)
|
||||||
|
.map(|message| tag_picker(false, message))
|
||||||
};
|
};
|
||||||
|
|
||||||
container(column![header, title_bar, content])
|
container(column![header, title_bar, content])
|
||||||
@@ -797,14 +812,19 @@ impl PropertiesPanel {
|
|||||||
.padding([4, 10]);
|
.padding([4, 10]);
|
||||||
|
|
||||||
let mut sections = column![].spacing(0);
|
let mut sections = column![].spacing(0);
|
||||||
|
self.rendering_quick.set(true);
|
||||||
for section in &self.sections {
|
for section in &self.sections {
|
||||||
sections = sections.push(self.render_section(section));
|
sections = sections.push(self.render_section(section));
|
||||||
}
|
}
|
||||||
|
self.rendering_quick.set(false);
|
||||||
|
|
||||||
let content = scrollable(sections.width(Length::Fill))
|
let content = Element::from(
|
||||||
.spacing(8)
|
scrollable(sections.width(Length::Fill))
|
||||||
.width(Length::Fill)
|
.spacing(8)
|
||||||
.height(Length::Shrink);
|
.width(Length::Fill)
|
||||||
|
.height(Length::Shrink),
|
||||||
|
)
|
||||||
|
.map(|message| tag_picker(true, message));
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
container(column![title, content].spacing(0))
|
container(column![title, content].spacing(0))
|
||||||
@@ -1002,7 +1022,7 @@ impl PropertiesPanel {
|
|||||||
if field == "background_color" {
|
if field == "background_color" {
|
||||||
let selector = crate::ui::color_select::color_selector(
|
let selector = crate::ui::color_select::color_selector(
|
||||||
color,
|
color,
|
||||||
self.bg_color_picker_open,
|
self.bg_color_picker_open && self.picker_here(),
|
||||||
crate::ui::color_select::ColorExtras {
|
crate::ui::color_select::ColorExtras {
|
||||||
by_layer: true,
|
by_layer: true,
|
||||||
by_block: true,
|
by_block: true,
|
||||||
@@ -1035,7 +1055,7 @@ impl PropertiesPanel {
|
|||||||
| "background_fill_color"
|
| "background_fill_color"
|
||||||
| "indicator_fill_color"
|
| "indicator_fill_color"
|
||||||
) {
|
) {
|
||||||
let open = self.open_color_field.as_deref() == Some(field);
|
let open = self.open_color_field.as_deref() == Some(field) && self.picker_here();
|
||||||
let fsel = field.to_string();
|
let fsel = field.to_string();
|
||||||
let full_palette_field = field.to_string();
|
let full_palette_field = field.to_string();
|
||||||
let extras = if field == "dim_text_fill_color" {
|
let extras = if field == "dim_text_fill_color" {
|
||||||
@@ -1078,7 +1098,7 @@ impl PropertiesPanel {
|
|||||||
let selector = crate::ui::color_select::color_selector_with_name(
|
let selector = crate::ui::color_select::color_selector_with_name(
|
||||||
color,
|
color,
|
||||||
display_name,
|
display_name,
|
||||||
self.color_picker_open,
|
self.color_picker_open && self.picker_here(),
|
||||||
crate::ui::color_select::ColorExtras {
|
crate::ui::color_select::ColorExtras {
|
||||||
by_layer: true,
|
by_layer: true,
|
||||||
by_block: true,
|
by_block: true,
|
||||||
@@ -1093,7 +1113,7 @@ impl PropertiesPanel {
|
|||||||
|
|
||||||
fn render_color_varies_row<'a>(&'a self, label: &'a str) -> Element<'a, Message> {
|
fn render_color_varies_row<'a>(&'a self, label: &'a str) -> Element<'a, Message> {
|
||||||
let selector = crate::ui::color_select::color_selector_varies(
|
let selector = crate::ui::color_select::color_selector_varies(
|
||||||
self.color_picker_open,
|
self.color_picker_open && self.picker_here(),
|
||||||
crate::ui::color_select::ColorExtras {
|
crate::ui::color_select::ColorExtras {
|
||||||
by_layer: true,
|
by_layer: true,
|
||||||
by_block: true,
|
by_block: true,
|
||||||
@@ -1352,7 +1372,7 @@ impl PropertiesPanel {
|
|||||||
})
|
})
|
||||||
.width(Length::Fill);
|
.width(Length::Fill);
|
||||||
let caret = button(
|
let caret = button(
|
||||||
container(if self.edit_choice_open {
|
container(if self.edit_choice_open && self.picker_here() {
|
||||||
crate::ui::icons::themed_arrow_up(9.0)
|
crate::ui::icons::themed_arrow_up(9.0)
|
||||||
} else {
|
} else {
|
||||||
crate::ui::icons::themed_arrow_down(9.0)
|
crate::ui::icons::themed_arrow_down(9.0)
|
||||||
@@ -1405,7 +1425,7 @@ impl PropertiesPanel {
|
|||||||
})
|
})
|
||||||
.width(Length::Fill);
|
.width(Length::Fill);
|
||||||
|
|
||||||
if !self.edit_choice_open {
|
if !(self.edit_choice_open && self.picker_here()) {
|
||||||
return prop_row_with_active(label, head.into(), active);
|
return prop_row_with_active(label, head.into(), active);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1609,7 +1629,7 @@ impl PropertiesPanel {
|
|||||||
text(crate::ui::text_util::elide(current, 16))
|
text(crate::ui::text_util::elide(current, 16))
|
||||||
.size(FONT_SZ)
|
.size(FONT_SZ)
|
||||||
.width(Length::Fill),
|
.width(Length::Fill),
|
||||||
if self.hatch_pattern_picker_open {
|
if self.hatch_pattern_picker_open && self.picker_here() {
|
||||||
crate::ui::icons::themed_arrow_up(FONT_SZ)
|
crate::ui::icons::themed_arrow_up(FONT_SZ)
|
||||||
} else {
|
} else {
|
||||||
crate::ui::icons::themed_arrow_down(FONT_SZ)
|
crate::ui::icons::themed_arrow_down(FONT_SZ)
|
||||||
@@ -1629,7 +1649,7 @@ impl PropertiesPanel {
|
|||||||
})),
|
})),
|
||||||
text_color: palette.background.base.text,
|
text_color: palette.background.base.text,
|
||||||
border: Border {
|
border: Border {
|
||||||
color: if self.hatch_pattern_picker_open {
|
color: if self.hatch_pattern_picker_open && self.picker_here() {
|
||||||
palette.primary.base.color
|
palette.primary.base.color
|
||||||
} else {
|
} else {
|
||||||
palette.background.neutral.color
|
palette.background.neutral.color
|
||||||
@@ -1643,7 +1663,7 @@ impl PropertiesPanel {
|
|||||||
.padding([COMBO_PAD_V, 6.0])
|
.padding([COMBO_PAD_V, 6.0])
|
||||||
.width(Length::Fill);
|
.width(Length::Fill);
|
||||||
|
|
||||||
if !self.hatch_pattern_picker_open {
|
if !(self.hatch_pattern_picker_open && self.picker_here()) {
|
||||||
return prop_row_widget(label, head.into());
|
return prop_row_widget(label, head.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2370,3 +2390,18 @@ mod tests {
|
|||||||
assert!((0.01..=100.0).contains(&scale));
|
assert!((0.01..=100.0).contains(&scale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Marks a dropdown toggle with the surface it came from (see
|
||||||
|
/// `PropertiesPanel::picker_in_quick`).
|
||||||
|
fn tag_picker(quick: bool, message: Message) -> Message {
|
||||||
|
match message {
|
||||||
|
Message::PropColorPickerToggle
|
||||||
|
| Message::PropBgColorPickerToggle
|
||||||
|
| Message::PropColorFieldToggle(_)
|
||||||
|
| Message::PropEditChoiceToggle
|
||||||
|
| Message::PropHatchPatternPickerToggle(_) => {
|
||||||
|
Message::PropPickerSurface(quick, Box::new(message))
|
||||||
|
}
|
||||||
|
other => other,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user