forked from 1b-agent/opencadstudio-upstream
feat(properties): collapse the panel to a vertical bar on a narrow window
When the window is too narrow for the full properties panel it now collapses to a slim vertical "Properties" bar (its label drawn rotated 90° on a canvas), freeing width for the viewport. Clicking the bar expands the panel back out alongside the bar; clicking it again re-collapses (props_expanded state + TogglePropertiesBar). Reuses the rotated-label bar helper originally built for the Start page. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
e2a56033d4
commit
19a7343c80
3 files changed
+108
-3
No files matched your search
@@ -232,6 +232,9 @@ pub(super) struct OpenCADStudio {
|
||||
/// Which Start-page section is shown when the page is too narrow for all
|
||||
/// three side by side and falls back to a tab bar.
|
||||
start_section: StartSection,
|
||||
/// When the window is too narrow the properties panel collapses to a
|
||||
/// vertical bar; this is the user's toggle to expand it back out.
|
||||
props_expanded: bool,
|
||||
/// Read-only editor buffer backing the command-line history dropdown, so
|
||||
/// the log can be drag-selected across lines and copied (issue #232).
|
||||
/// Rebuilt from the history each time the dropdown is opened.
|
||||
@@ -1129,6 +1132,8 @@ pub enum Message {
|
||||
OpenUrl(String),
|
||||
/// Select which section a narrow (tabbed) Start page shows.
|
||||
StartSectionSelect(StartSection),
|
||||
/// Expand/collapse the properties panel when it has shrunk to a bar.
|
||||
TogglePropertiesBar,
|
||||
/// Scroll the status-bar layout-tab strip horizontally by `delta` px
|
||||
/// (negative = left). Driven by the ‹ › arrows next to the tabs.
|
||||
ScrollLayoutTabs(f32),
|
||||
@@ -1975,6 +1980,7 @@ impl OpenCADStudio {
|
||||
command_line: CommandLine::new(),
|
||||
patrons: Vec::new(),
|
||||
start_section: StartSection::default(),
|
||||
props_expanded: false,
|
||||
history_content: iced::widget::text_editor::Content::new(),
|
||||
status_bar: StatusBar::new(),
|
||||
cursor_pos: Point::ORIGIN,
|
||||
|
||||
@@ -226,6 +226,11 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::TogglePropertiesBar => {
|
||||
self.props_expanded = !self.props_expanded;
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::ScrollLayoutTabs(dx) => iced::widget::operation::scroll_by(
|
||||
iced::advanced::widget::Id::new(crate::ui::statusbar::LAYOUT_TABS_SCROLL_ID),
|
||||
iced::widget::scrollable::AbsoluteOffset { x: dx, y: 0.0 },
|
||||
|
||||
+97
-3
@@ -8,8 +8,8 @@ use crate::scene::view::viewport_pane::ViewportPane;
|
||||
use crate::scene::{VIEWCUBE_PAD, VIEWCUBE_REGION_PX};
|
||||
use crate::ui::wrap_bar::WrapFlow;
|
||||
use iced::widget::{
|
||||
button, column, container, mouse_area, pane_grid, responsive, row, shader, stack, text, Row,
|
||||
Space,
|
||||
button, canvas, column, container, mouse_area, pane_grid, responsive, row, shader, stack, text,
|
||||
Row, Space,
|
||||
};
|
||||
use iced::window;
|
||||
use iced::{keyboard, Background, Border, Color, Element, Fill, Subscription, Task, Theme};
|
||||
@@ -1143,7 +1143,17 @@ impl OpenCADStudio {
|
||||
let properties_el: Element<'_, Message> = if tab.is_start {
|
||||
Space::new().into()
|
||||
} else if self.show_properties && !self.clean_screen {
|
||||
tab.properties.view()
|
||||
// On a narrow window the panel collapses to a vertical "Properties"
|
||||
// bar to free width for the viewport; clicking the bar expands it.
|
||||
let narrow = self.win_size.0 < 1000.0;
|
||||
let bar = || collapse_bar("Properties", Message::TogglePropertiesBar);
|
||||
if narrow && !self.props_expanded {
|
||||
bar()
|
||||
} else if narrow {
|
||||
row![bar(), tab.properties.view()].into()
|
||||
} else {
|
||||
tab.properties.view()
|
||||
}
|
||||
} else {
|
||||
Space::new().into()
|
||||
};
|
||||
@@ -1987,6 +1997,90 @@ fn pane_mouse_area<'a>(idx: usize) -> Element<'a, Message> {
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Canvas that draws a label rotated 90° (for a collapsed panel's bar).
|
||||
struct VBarLabel {
|
||||
text: String,
|
||||
color: Color,
|
||||
}
|
||||
|
||||
impl canvas::Program<Message> for VBarLabel {
|
||||
type State = ();
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
_state: &(),
|
||||
renderer: &iced::Renderer,
|
||||
_theme: &Theme,
|
||||
bounds: iced::Rectangle,
|
||||
_cursor: iced::advanced::mouse::Cursor,
|
||||
) -> Vec<canvas::Geometry> {
|
||||
let mut frame = canvas::Frame::new(renderer, bounds.size());
|
||||
frame.with_save(|frame| {
|
||||
frame.translate(iced::Vector::new(bounds.width / 2.0, bounds.height / 2.0));
|
||||
frame.rotate(iced::Radians(std::f32::consts::FRAC_PI_2));
|
||||
frame.fill_text(canvas::Text {
|
||||
content: self.text.clone(),
|
||||
position: iced::Point::ORIGIN,
|
||||
color: self.color,
|
||||
size: iced::Pixels(13.0),
|
||||
align_x: iced::advanced::text::Alignment::Center,
|
||||
align_y: iced::alignment::Vertical::Center,
|
||||
shaping: iced::advanced::text::Shaping::Advanced,
|
||||
..Default::default()
|
||||
});
|
||||
});
|
||||
vec![frame.into_geometry()]
|
||||
}
|
||||
}
|
||||
|
||||
/// A collapsed panel rendered as a tall narrow bar with its name written along
|
||||
/// it, rotated 90°. Pressing it emits `on_press`.
|
||||
pub(super) fn collapse_bar<'a>(name: &str, on_press: Message) -> Element<'a, Message> {
|
||||
const LABEL: Color = Color {
|
||||
r: 0.72,
|
||||
g: 0.72,
|
||||
b: 0.74,
|
||||
a: 1.0,
|
||||
};
|
||||
const BAR_BG: Color = Color {
|
||||
r: 0.13,
|
||||
g: 0.13,
|
||||
b: 0.14,
|
||||
a: 1.0,
|
||||
};
|
||||
const BAR_BORDER: Color = Color {
|
||||
r: 0.22,
|
||||
g: 0.22,
|
||||
b: 0.24,
|
||||
a: 1.0,
|
||||
};
|
||||
|
||||
let label = canvas(VBarLabel {
|
||||
text: name.to_string(),
|
||||
color: LABEL,
|
||||
})
|
||||
.width(Fill)
|
||||
.height(Fill);
|
||||
|
||||
mouse_area(
|
||||
container(label)
|
||||
.width(iced::Length::Fixed(26.0))
|
||||
.height(Fill)
|
||||
.style(|_: &Theme| container::Style {
|
||||
background: Some(Background::Color(BAR_BG)),
|
||||
border: Border {
|
||||
color: BAR_BORDER,
|
||||
width: 1.0,
|
||||
radius: 0.0.into(),
|
||||
},
|
||||
..Default::default()
|
||||
}),
|
||||
)
|
||||
.interaction(iced::mouse::Interaction::Pointer)
|
||||
.on_press(on_press)
|
||||
.into()
|
||||
}
|
||||
|
||||
pub(super) fn start_page_view<'a>(
|
||||
patrons: &'a [(String, i64)],
|
||||
recents: &'a [std::path::PathBuf],
|
||||
|
||||
Reference in new issue
Block a user