forked from 1b-agent/opencadstudio-upstream
feat(ui): replace app-menu logo with a quick-access file toolbar
Remove the OCS-logo button and the dropdown menu it opened; the top strip now shows direct New / Open / Save / Save As / Print buttons ahead of the undo/redo controls. Drop the HELP and OPTIONS commands (HELP dumped text to the command line, OPTIONS aliased the drafting-settings popup). The app-menu overlay is gone, so its rendering code, MENU_ITEMS, four dead messages, and the LOGO_RED / GEAR / HELP assets are removed. The recents list it held is the only survivor — moved into OpenCADStudio.recent_files via a new app/recent.rs, backing the Start page's Recent Documents panel. Quick-access icons are redrawn in a cleaner style (file-plus, folder-open, device-floppy, file-export, printer) and tinted light so they read on the dark strip; FOLDER / DOC keep their old glyphs for the file browser. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
2bc5c2a686
commit
7bab7c7b8d
17 files changed
+154
-643
No files matched your search
@@ -154,9 +154,9 @@ impl OpenCADStudio {
|
||||
"POLAR" => {
|
||||
return Some(Task::done(Message::TogglePolar));
|
||||
}
|
||||
// DSETTINGS / OSNAP / OPTIONS — open the drafting-settings popup, which
|
||||
// is OCS's settings surface (the persisted DYN/ORTHO/POLAR/OSNAP prefs).
|
||||
"DSETTINGS" | "OSNAP" | "OPTIONS" | "OP" => {
|
||||
// DSETTINGS / OSNAP — open the drafting-settings popup, which is OCS's
|
||||
// settings surface (the persisted DYN/ORTHO/POLAR/OSNAP prefs).
|
||||
"DSETTINGS" | "OSNAP" => {
|
||||
return Some(Task::done(Message::ToggleSnapPopup));
|
||||
}
|
||||
// UNITS — open the drawing-units picker (linear / angular format).
|
||||
|
||||
@@ -3,25 +3,6 @@ use super::*;
|
||||
impl OpenCADStudio {
|
||||
pub(super) fn dispatch_view(&mut self, cmd: &str, i: usize) -> Option<Task<Message>> {
|
||||
match cmd {
|
||||
"HELP" | "?" => {
|
||||
self.command_line.push_output(
|
||||
"Draw: LINE CIRCLE ARC PLINE RECTANG(RECT) POLYGON(POLY) POINT ELLIPSE SPLINE RAY XLINE HATCH DONUT REVCLOUD WIPEOUT MLINE ATTDEF | \
|
||||
Modify: MOVE COPY ROTATE SCALE MIRROR ERASE OFFSET EXTEND FILLET CHAMFER STRETCH EXPLODE TRIM BREAK JOIN LENGTHEN ALIGN PEDIT | \
|
||||
Array: ARRAY ARRAYRECT ARRAYPOLAR ARRAYPATH | \
|
||||
Text: TEXT MTEXT LEADER MLEADER | \
|
||||
Dimension: DIMLINEAR DIMALIGNED DIMANGULAR DIMRADIUS DIMDIAMETER DIMCONTINUE DIMBASELINE | \
|
||||
Annotation: TOLERANCE | \
|
||||
Inquiry: DIST ID AREA LIST FIND FINDALL COUNT QSELECT | Draw on entity: DIVIDE MEASURE | \
|
||||
Attributes: ATTEDIT ATTDISP | \
|
||||
Utilities: FLATTEN LAYISO LAYUNISO | \
|
||||
View: ZOOM EXTENTS ZOOM WINDOW VIEW LIST/SAVE/RESTORE/DELETE | \
|
||||
Layer: LAYER LIST/NEW/ON/OFF/FREEZE/THAW/LOCK/UNLOCK/COLOR/SET | \
|
||||
Viewport: MVIEW VPLAYER VPORTS MS PS DRAWORDER | \
|
||||
Tables: STYLE DIMSTYLE LINETYPE UCS RENAME PURGE | \
|
||||
File: NEW OPEN SAVE SAVEAS PRINT PURGE UNDO REDO"
|
||||
);
|
||||
}
|
||||
|
||||
"DONATE" => {
|
||||
crate::sys::open_url("https://patreon.com/HakanSeven12");
|
||||
self.command_line.push_info("Opening Patreon page...");
|
||||
|
||||
+6
-12
@@ -14,6 +14,7 @@ mod mtext_editor;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod plugin_host;
|
||||
mod properties;
|
||||
mod recent;
|
||||
mod settings;
|
||||
mod style_ops;
|
||||
mod text_inline;
|
||||
@@ -155,7 +156,7 @@ pub struct QSelectState {
|
||||
pub append: bool,
|
||||
}
|
||||
use crate::snap::Snapper;
|
||||
use crate::ui::{AppMenu, CommandLine, Ribbon, StatusBar};
|
||||
use crate::ui::{CommandLine, Ribbon, StatusBar};
|
||||
use acadrust::types::{Color as AcadColor, LineWeight};
|
||||
use acadrust::CadDocument;
|
||||
|
||||
@@ -192,7 +193,8 @@ pub(super) struct OpenCADStudio {
|
||||
active_tab: usize,
|
||||
tab_counter: usize,
|
||||
ribbon: Ribbon,
|
||||
app_menu: AppMenu,
|
||||
/// Recently opened files, newest first — backs the Start page panel.
|
||||
recent_files: Vec<std::path::PathBuf>,
|
||||
command_line: CommandLine,
|
||||
/// Paying Patreon supporters shown on the Start page (name, pledge cents),
|
||||
/// fetched once at boot, highest pledge first.
|
||||
@@ -1121,12 +1123,6 @@ pub enum Message {
|
||||
command: String,
|
||||
path: Option<std::path::PathBuf>,
|
||||
},
|
||||
// ── Application menu ──────────────────────────────────────────────────
|
||||
ToggleAppMenu,
|
||||
CloseAppMenu,
|
||||
/// Close the menu and immediately dispatch a CAD command.
|
||||
CloseAppMenuAndRun(String),
|
||||
AppMenuSearch(String),
|
||||
// ── Document tabs ──────────────────────────────────────────────────────
|
||||
/// Create a new empty document tab.
|
||||
TabNew,
|
||||
@@ -1918,16 +1914,14 @@ impl OpenCADStudio {
|
||||
// Boot with only the Welcome/Start tab. The user creates drawings
|
||||
// explicitly (File → New); we never auto-spawn Drawing1.
|
||||
let start_tab = DocumentTab::new_start();
|
||||
let mut app_menu = AppMenu::new();
|
||||
// Restore recents from disk so the Start page lists them across runs.
|
||||
app_menu.load_persistent_recents();
|
||||
let mut app = Self {
|
||||
start: Instant::now(),
|
||||
tabs: vec![start_tab],
|
||||
active_tab: 0,
|
||||
tab_counter: 0,
|
||||
ribbon: Ribbon::new(),
|
||||
app_menu,
|
||||
// Restore recents from disk so the Start page lists them across runs.
|
||||
recent_files: recent::load_recent_files(),
|
||||
command_line: CommandLine::new(),
|
||||
patrons: Vec::new(),
|
||||
history_content: iced::widget::text_editor::Content::new(),
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
//! Persistent recent-files store backing the Start page's Recent Documents
|
||||
//! panel. Stored as plain text on disk (one path per line, newest first) next
|
||||
//! to the other per-user config, so no serialization crate is pulled in just
|
||||
//! for this.
|
||||
|
||||
use super::OpenCADStudio;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
impl OpenCADStudio {
|
||||
/// Record a freshly opened file at the top of the recents list.
|
||||
pub(super) fn push_recent(&mut self, path: PathBuf) {
|
||||
self.recent_files.retain(|r| r != &path);
|
||||
self.recent_files.insert(0, path);
|
||||
self.recent_files.truncate(20);
|
||||
// Best-effort persist; silent on failure (read-only home, full disk).
|
||||
let _ = save_recents(&self.recent_files);
|
||||
}
|
||||
|
||||
/// Drop a path from the recents list (manual removal from the Start page).
|
||||
pub(super) fn remove_recent(&mut self, path: &Path) {
|
||||
self.recent_files.retain(|r| r.as_path() != path);
|
||||
let _ = save_recents(&self.recent_files);
|
||||
}
|
||||
}
|
||||
|
||||
/// Rehydrate the recents list from disk. Call once at app boot.
|
||||
pub(super) fn load_recent_files() -> Vec<PathBuf> {
|
||||
let Some(path) = recents_file_path() else {
|
||||
return vec![];
|
||||
};
|
||||
let Ok(body) = std::fs::read_to_string(path) else {
|
||||
return vec![];
|
||||
};
|
||||
body.lines()
|
||||
.filter(|l| !l.trim().is_empty())
|
||||
.map(PathBuf::from)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn recents_file_path() -> Option<PathBuf> {
|
||||
let base: PathBuf = if cfg!(target_os = "windows") {
|
||||
std::env::var_os("APPDATA").map(PathBuf::from)?
|
||||
} else if cfg!(target_os = "macos") {
|
||||
let home = std::env::var_os("HOME")?;
|
||||
let mut p = PathBuf::from(home);
|
||||
p.push("Library");
|
||||
p.push("Application Support");
|
||||
p
|
||||
} else if let Some(d) = std::env::var_os("XDG_CONFIG_HOME") {
|
||||
PathBuf::from(d)
|
||||
} else {
|
||||
let home = std::env::var_os("HOME")?;
|
||||
let mut p = PathBuf::from(home);
|
||||
p.push(".config");
|
||||
p
|
||||
};
|
||||
let mut p = base;
|
||||
p.push("OpenCADStudio");
|
||||
Some(p.join("recent.txt"))
|
||||
}
|
||||
|
||||
fn save_recents(list: &[PathBuf]) -> std::io::Result<()> {
|
||||
let Some(path) = recents_file_path() else {
|
||||
return Ok(());
|
||||
};
|
||||
if let Some(dir) = path.parent() {
|
||||
std::fs::create_dir_all(dir)?;
|
||||
}
|
||||
let body: String = list
|
||||
.iter()
|
||||
.map(|p| p.to_string_lossy().into_owned())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
std::fs::write(path, body)
|
||||
}
|
||||
@@ -240,7 +240,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
|
||||
caches.corrupt_dropped
|
||||
));
|
||||
}
|
||||
self.app_menu.push_recent(path.clone());
|
||||
self.push_recent(path.clone());
|
||||
|
||||
let current_is_empty = {
|
||||
let t = &self.tabs[self.active_tab];
|
||||
|
||||
+1
-19
@@ -243,7 +243,7 @@ impl OpenCADStudio {
|
||||
}
|
||||
|
||||
Message::RecentRemove(path) => {
|
||||
self.app_menu.remove_recent(&path);
|
||||
self.remove_recent(&path);
|
||||
Task::none()
|
||||
}
|
||||
|
||||
@@ -616,24 +616,6 @@ impl OpenCADStudio {
|
||||
Task::none()
|
||||
}
|
||||
|
||||
// ── Application menu ──────────────────────────────────────────
|
||||
Message::ToggleAppMenu => {
|
||||
self.app_menu.toggle();
|
||||
Task::none()
|
||||
}
|
||||
Message::CloseAppMenu => {
|
||||
self.app_menu.close();
|
||||
Task::none()
|
||||
}
|
||||
Message::CloseAppMenuAndRun(cmd) => {
|
||||
self.app_menu.close();
|
||||
self.dispatch_command(&cmd.clone())
|
||||
}
|
||||
Message::AppMenuSearch(s) => {
|
||||
self.app_menu.search = s;
|
||||
Task::none()
|
||||
}
|
||||
|
||||
// ── Document tabs ─────────────────────────────────────────────
|
||||
Message::TabNew => {
|
||||
self.tab_counter += 1;
|
||||
|
||||
+1
-2
@@ -1084,7 +1084,7 @@ impl OpenCADStudio {
|
||||
// Properties / layers panels carry no useful state on the Start tab.
|
||||
// Replace the properties panel with a Recent Documents list there.
|
||||
let properties_el: Element<'_, Message> = if tab.is_start {
|
||||
recent_files_panel(&self.app_menu.recent)
|
||||
recent_files_panel(&self.recent_files)
|
||||
} else if self.show_properties && !self.clean_screen {
|
||||
tab.properties.view()
|
||||
} else {
|
||||
@@ -1304,7 +1304,6 @@ impl OpenCADStudio {
|
||||
|
||||
let composed = stack![
|
||||
main_ui,
|
||||
self.app_menu.view(),
|
||||
snap_layer,
|
||||
scale_layer,
|
||||
statusbar_menu_layer,
|
||||
|
||||
Reference in new issue
Block a user