feat(ui): Add menu bar and customizable quick toolbar (v0.7.0)
- Menu bar groups all functions: File (import/MRU/exports), View (zoom/standard views/ortho/unit), Measure (7 checkable modes with hotkey hints), Transform (align/drag/gizmo/rotate), Tools (interference/section), QuickBar (customize/reset) - QuickBarViewModel registry: per-button visibility via XAML indexer binding QuickBar[Key].IsChecked; buttons keep static bindings - Common-user defaults visible (import/recent/zoom/iso/ortho/point/ distance/circle/angle/interference/section/clear/unit); the rest live in menus; selection persists in settings.json QuickBarKeys - Section parameter bar is its own row, shown only while section is enabled (with close button); no longer occupies space permanently - Bump version to 0.7.0; update ARCHITECTURE/CLAUDE docs (Phase 16) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -463,6 +463,29 @@ WPF retained-mode 每幀重走 visual tree → frame rate 崩。瀏覽模式因
|
||||
|
||||
---
|
||||
|
||||
## Development Phases — 第八輪(UI 重整 v0.7.0)
|
||||
|
||||
### Phase 16 — 選單列 + 可自訂快速列(工作量:M)
|
||||
|
||||
**問題:** 功能累積後單一工具列 30+ 顆按鈕擠在一排,視窗不夠寬就溢出到「▾」,難找難按。
|
||||
|
||||
- [x] **選單列**(Menu):全部功能分類下拉 — 檔案(匯入/MRU/四種匯出)、視圖(全覽/標準視圖/正交/單位)、
|
||||
量測(7 種模式 checkable + 快速鍵提示 + 清除)、變換(對齊/三點/拖曳/操作器/旋轉XYZ)、
|
||||
工具(干涉/剖面)、快速列(自訂按鈕勾選 + 恢復預設)
|
||||
- [x] **快速工具列**(`QuickBarViewModel`):只顯示使用者勾選的常用按鈕;
|
||||
註冊表定義全部按鈕(key/選單名/預設值),XAML 以索引子綁定
|
||||
`Visibility="{Binding QuickBar[Key].IsChecked, Converter=BoolToVis}"`(按鈕本體與綁定保持靜態)
|
||||
- [x] 預設常用:匯入、最近、全覽、等角、正交、點、距離、圓、角度、干涉、剖面、清除、mm⇄in;
|
||||
其餘(邊/面/面距/對齊/三點/旋轉/拖曳/操作器/四種匯出/前上右視圖)預設收進選單
|
||||
- [x] 勾選清單隨 settings.json(`QuickBarKeys`)保存;null/新按鈕用註冊表預設值
|
||||
- [x] **剖面參數列**獨立成第三列,只在 `SectionEnabled` 時顯示(含「✕ 關閉」);
|
||||
平常整條隱藏,不再常駐佔位
|
||||
|
||||
**驗收:** 選單所有功能可用(checkable 與工具列 toggle 同步);快速列勾選即時增減、重開保留;
|
||||
既有快速鍵 P/D/E/F/C/A/M + Esc 不受影響
|
||||
|
||||
---
|
||||
|
||||
## Future Extensions(下一輪)
|
||||
|
||||
- **大檔重開快取** — 匯入成功後把三角網格 + 裝配樹序列化成 sidecar 快取檔(以來源檔 hash 驗證),
|
||||
|
||||
@@ -47,6 +47,10 @@ dotnet publish src/STPViewer -c Release -o publish/STPViewer
|
||||
(量孔對孔 pitch 靠這個)。不要把圓心吸附拿掉或改成永遠優先頂點
|
||||
- 鍵盤快速鍵在 `MainWindow.Window_PreviewKeyDown`:**焦點在 TextBoxBase/ComboBox 時直接 return**
|
||||
(樹搜尋框、剖面數值框要能打字),新增輸入控件不用再各自處理
|
||||
- UI 三層(v0.7.0):**選單列**(全部功能,分類下拉)+ **快速列**(`QuickBarViewModel` 註冊表,
|
||||
使用者勾選常用按鈕,XAML 索引子綁定 `QuickBar[Key].IsChecked` 控 Visibility,按鈕本體維持靜態綁定)+
|
||||
**剖面參數列**(只在 SectionEnabled 顯示)。新增功能要三處都接:選單分類、快速列註冊表
|
||||
(含預設值)+ 對應 XAML 按鈕;勾選清單存 settings.json `QuickBarKeys`(null = 預設)
|
||||
- 使用者設定 `SettingsService`(%LOCALAPPDATA%\STPViewer\settings.json):視窗(MainWindow 管)+
|
||||
單位/MRU(VM `LoadSettings`/`SaveSettingsInto`);壞檔回預設、儲存失敗靜默
|
||||
- 匯出 STEP 走 `CADability.ExportStep.WriteToFile(file, Project.CreateSimpleProject()+Model.Add)`;
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace STPViewer.Converters;
|
||||
|
||||
/// <summary>完整路徑 → 檔名(選單「最近檔案」顯示用;tooltip 仍給完整路徑)</summary>
|
||||
public class FileNameConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
||||
value is string s ? System.IO.Path.GetFileName(s) : "";
|
||||
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
+178
-40
@@ -12,111 +12,249 @@
|
||||
|
||||
<Window.Resources>
|
||||
<conv:EnumToBoolConverter x:Key="ModeConv" />
|
||||
<conv:FileNameConverter x:Key="FileNameConv" />
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis" />
|
||||
<Style x:Key="ModeButton" TargetType="ToggleButton">
|
||||
<Setter Property="Padding" Value="8,4" />
|
||||
<Setter Property="Margin" Value="2,0" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
</Style>
|
||||
<Style x:Key="QuickButton" TargetType="Button">
|
||||
<Setter Property="Padding" Value="8,4" />
|
||||
<Setter Property="Margin" Value="2,0" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
<DockPanel>
|
||||
<!-- ─── 工具列 ─── -->
|
||||
<!-- ─── 選單列(全部功能,分類下拉)─── -->
|
||||
<Menu DockPanel.Dock="Top">
|
||||
<MenuItem Header="檔案(_F)">
|
||||
<MenuItem Header="📂 匯入…" Command="{Binding ImportCommand}"
|
||||
ToolTip="匯入 STP/STEP/STL/DXF(可複選,也可直接拖放到視窗)" />
|
||||
<MenuItem Header="最近檔案" ItemsSource="{Binding RecentFiles}">
|
||||
<MenuItem.ItemContainerStyle>
|
||||
<Style TargetType="MenuItem">
|
||||
<Setter Property="Header" Value="{Binding Converter={StaticResource FileNameConv}}" />
|
||||
<Setter Property="ToolTip" Value="{Binding}" />
|
||||
<Setter Property="Command"
|
||||
Value="{Binding DataContext.ImportRecentCommand, RelativeSource={RelativeSource AncestorType=Menu}}" />
|
||||
<Setter Property="CommandParameter" Value="{Binding}" />
|
||||
</Style>
|
||||
</MenuItem.ItemContainerStyle>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="💾 匯出量測 CSV…" Command="{Binding ExportCsvCommand}" />
|
||||
<MenuItem Header="📷 視圖截圖 PNG…" Command="{Binding SaveScreenshotCommand}"
|
||||
ToolTip="3D 視圖截圖存 PNG(2x 解析度)" />
|
||||
<MenuItem Header="📤 匯出 STEP…" Command="{Binding ExportStepFileCommand}"
|
||||
ToolTip="把可見檔案(目前對齊位置)匯出成新 STEP 檔;不動原始檔" />
|
||||
<MenuItem Header="📐 匯出 STL…" Command="{Binding ExportStlFileCommand}"
|
||||
ToolTip="先設定範圍/格式/單位/精度,確認再匯出" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="視圖(_V)">
|
||||
<MenuItem Header="🔍 縮放至全部" Command="{Binding ZoomAllCommand}" />
|
||||
<Separator />
|
||||
<MenuItem Header="等角視圖" Command="{Binding SetStandardViewCommand}" CommandParameter="Iso" />
|
||||
<MenuItem Header="前視圖" Command="{Binding SetStandardViewCommand}" CommandParameter="Front"
|
||||
ToolTip="-Y 方向看,Z 向上" />
|
||||
<MenuItem Header="上視圖" Command="{Binding SetStandardViewCommand}" CommandParameter="Top"
|
||||
ToolTip="+Z 往下看" />
|
||||
<MenuItem Header="右視圖" Command="{Binding SetStandardViewCommand}" CommandParameter="Right"
|
||||
ToolTip="+X 方向看,Z 向上" />
|
||||
<Separator />
|
||||
<MenuItem Header="正交投影" IsCheckable="True" IsChecked="{Binding OrthographicView}"
|
||||
ToolTip="平行投影,量尺寸不受透視變形;取消勾選切回透視" />
|
||||
<MenuItem Header="單位顯示 inch(mm ⇄ in)" IsCheckable="True" IsChecked="{Binding UseInch}"
|
||||
ToolTip="既有量測即時換算;內部一律存 mm" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="量測(_M)">
|
||||
<MenuItem Header="📍 點座標" IsCheckable="True" InputGestureText="P"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Point}"
|
||||
ToolTip="量測點座標(吸附頂點/圓心)" />
|
||||
<MenuItem Header="📏 兩點距離" IsCheckable="True" InputGestureText="D"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Distance}"
|
||||
ToolTip="兩點距離 + ΔXYZ(點到圓邊會吸圓心 → 可量孔對孔 pitch)" />
|
||||
<MenuItem Header="📐 邊長" IsCheckable="True" InputGestureText="E"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Edge}"
|
||||
ToolTip="邊長(直線/曲線/圓弧)" />
|
||||
<MenuItem Header="⬛ 面" IsCheckable="True" InputGestureText="F"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Face}"
|
||||
ToolTip="面積 + 曲面類型/法向量" />
|
||||
<MenuItem Header="⭕ 圓" IsCheckable="True" InputGestureText="C"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Circle}"
|
||||
ToolTip="圓心/半徑/直徑/周長" />
|
||||
<MenuItem Header="∠ 角度" IsCheckable="True" InputGestureText="A"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Angle}"
|
||||
ToolTip="兩面/兩邊夾角(點兩個面或靠近直線邊)" />
|
||||
<MenuItem Header="⇔ 面距" IsCheckable="True" InputGestureText="M"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=FaceDistance}"
|
||||
ToolTip="面到面最短距離(網格近似)" />
|
||||
<Separator />
|
||||
<MenuItem Header="🧹 清除全部量測" Command="{Binding ClearMeasurementsCommand}"
|
||||
InputGestureText="Esc" ToolTip="Esc = 取消進行中量測/退出模式" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="變換(_T)">
|
||||
<MenuItem Header="🎯 兩點對齊(平移)" IsCheckable="True"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Align}"
|
||||
ToolTip="先點要移動零件上的點,再點目標點" />
|
||||
<MenuItem Header="🎯 三點對齊(旋轉+平移)" IsCheckable="True"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Align3}"
|
||||
ToolTip="先在要移動的檔案點 3 個特徵點,再到目標檔案點 3 個對應點(順序對應)" />
|
||||
<MenuItem Header="🖐 拖曳模式" IsCheckable="True"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Drag}"
|
||||
ToolTip="左鍵按住零件沿螢幕平面拖動,放開定位" />
|
||||
<MenuItem Header="⊹ 三軸操作器" IsCheckable="True" IsChecked="{Binding GizmoEnabled}"
|
||||
ToolTip="對樹面板選取的檔案顯示 XYZ 箭頭與旋轉環,每次放開即定位" />
|
||||
<Separator />
|
||||
<MenuItem Header="↻ 繞 X 軸 +90°" Command="{Binding RotateRootCommand}" CommandParameter="X"
|
||||
ToolTip="對樹面板選取的檔案,繞其中心旋轉(先在樹面板點選檔案)" />
|
||||
<MenuItem Header="↻ 繞 Y 軸 +90°" Command="{Binding RotateRootCommand}" CommandParameter="Y" />
|
||||
<MenuItem Header="↻ 繞 Z 軸 +90°" Command="{Binding RotateRootCommand}" CommandParameter="Z" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="工具(_L)">
|
||||
<MenuItem Header="🧩 干涉檢查" Command="{Binding CheckInterferenceCommand}"
|
||||
ToolTip="2 個以上可見檔案兩兩檢查是否相交;無相交時回報最小間隙" />
|
||||
<MenuItem Header="✂ 剖面檢視" IsCheckable="True" IsChecked="{Binding SectionEnabled}"
|
||||
ToolTip="開啟後下方出現剖面參數列(軸向/位置/反向)" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="快速列(_Q)">
|
||||
<MenuItem Header="自訂按鈕" ItemsSource="{Binding QuickBar.Items}"
|
||||
ToolTip="勾選要顯示在快速列的常用按鈕(隨設定保存)">
|
||||
<MenuItem.ItemContainerStyle>
|
||||
<Style TargetType="MenuItem">
|
||||
<Setter Property="Header" Value="{Binding Label}" />
|
||||
<Setter Property="IsCheckable" Value="True" />
|
||||
<Setter Property="IsChecked" Value="{Binding IsChecked}" />
|
||||
<Setter Property="StaysOpenOnClick" Value="True" />
|
||||
</Style>
|
||||
</MenuItem.ItemContainerStyle>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="恢復預設按鈕" Command="{Binding QuickBar.ResetDefaultsCommand}" />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
<!-- ─── 快速工具列(可自訂:選單「快速列 → 自訂按鈕」勾選)─── -->
|
||||
<ToolBarTray DockPanel.Dock="Top">
|
||||
<ToolBar>
|
||||
<Button Command="{Binding ImportCommand}" Padding="8,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding ImportCommand}"
|
||||
Visibility="{Binding QuickBar[Import].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="匯入 STP/STEP/STL/DXF(可複選,也可直接拖放到視窗)">📂 匯入</Button>
|
||||
<Button Click="Recent_Click" Padding="4,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Click="Recent_Click" Padding="4,4"
|
||||
Visibility="{Binding QuickBar[Recent].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="最近開啟的檔案">▾</Button>
|
||||
<Button Command="{Binding ZoomAllCommand}" Padding="8,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding ZoomAllCommand}"
|
||||
Visibility="{Binding QuickBar[ZoomAll].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="縮放至全部模型">🔍 全覽</Button>
|
||||
<Separator />
|
||||
<TextBlock Text="視圖:" VerticalAlignment="Center" Margin="4,0,2,0" />
|
||||
<Button Command="{Binding SetStandardViewCommand}" CommandParameter="Iso" Padding="6,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding SetStandardViewCommand}" CommandParameter="Iso"
|
||||
Visibility="{Binding QuickBar[ViewIso].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="等角視圖">等角</Button>
|
||||
<Button Command="{Binding SetStandardViewCommand}" CommandParameter="Front" Padding="6,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding SetStandardViewCommand}" CommandParameter="Front"
|
||||
Visibility="{Binding QuickBar[ViewFront].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="前視圖(-Y 方向看,Z 向上)">前</Button>
|
||||
<Button Command="{Binding SetStandardViewCommand}" CommandParameter="Top" Padding="6,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding SetStandardViewCommand}" CommandParameter="Top"
|
||||
Visibility="{Binding QuickBar[ViewTop].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="上視圖(+Z 往下看)">上</Button>
|
||||
<Button Command="{Binding SetStandardViewCommand}" CommandParameter="Right" Padding="6,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding SetStandardViewCommand}" CommandParameter="Right"
|
||||
Visibility="{Binding QuickBar[ViewRight].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="右視圖(+X 方向看,Z 向上)">右</Button>
|
||||
<ToggleButton IsChecked="{Binding OrthographicView}" Padding="6,4" FontSize="13" Margin="2,0"
|
||||
<ToggleButton Style="{StaticResource ModeButton}" IsChecked="{Binding OrthographicView}"
|
||||
Visibility="{Binding QuickBar[Ortho].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="正交投影(平行投影,量尺寸不受透視變形;再按切回透視)">正交</ToggleButton>
|
||||
<Separator />
|
||||
<TextBlock Text="量測:" VerticalAlignment="Center" Margin="4,0,2,0" />
|
||||
<ToggleButton Style="{StaticResource ModeButton}" ToolTip="量測點座標(吸附頂點/圓心)— 快速鍵 P"
|
||||
Visibility="{Binding QuickBar[Point].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Point}">📍 點</ToggleButton>
|
||||
<ToggleButton Style="{StaticResource ModeButton}" ToolTip="兩點距離 + ΔXYZ(點到圓邊會吸圓心 → 可量孔對孔 pitch)— 快速鍵 D"
|
||||
Visibility="{Binding QuickBar[Distance].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Distance}">📏 距離</ToggleButton>
|
||||
<ToggleButton Style="{StaticResource ModeButton}" ToolTip="邊長(直線/曲線/圓弧)— 快速鍵 E"
|
||||
Visibility="{Binding QuickBar[Edge].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Edge}">📐 邊</ToggleButton>
|
||||
<ToggleButton Style="{StaticResource ModeButton}" ToolTip="面積 + 曲面類型/法向量 — 快速鍵 F"
|
||||
Visibility="{Binding QuickBar[Face].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Face}">⬛ 面</ToggleButton>
|
||||
<ToggleButton Style="{StaticResource ModeButton}" ToolTip="圓心/半徑/直徑/周長 — 快速鍵 C"
|
||||
Visibility="{Binding QuickBar[Circle].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Circle}">⭕ 圓</ToggleButton>
|
||||
<ToggleButton Style="{StaticResource ModeButton}" ToolTip="兩面/兩邊夾角(點兩個面或靠近直線邊)— 快速鍵 A"
|
||||
Visibility="{Binding QuickBar[Angle].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Angle}">∠ 角度</ToggleButton>
|
||||
<ToggleButton Style="{StaticResource ModeButton}" ToolTip="面到面最短距離(網格近似)— 快速鍵 M"
|
||||
Visibility="{Binding QuickBar[FaceDistance].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=FaceDistance}">⇔ 面距</ToggleButton>
|
||||
<Separator />
|
||||
<ToggleButton Style="{StaticResource ModeButton}"
|
||||
ToolTip="兩點對齊(平移零件):先點要移動零件上的點,再點目標點"
|
||||
Visibility="{Binding QuickBar[Align].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Align}">🎯 對齊</ToggleButton>
|
||||
<ToggleButton Style="{StaticResource ModeButton}"
|
||||
ToolTip="三點對齊(旋轉+平移):先在要移動的檔案點 3 個特徵點,再到目標檔案點 3 個對應點(順序對應)"
|
||||
Visibility="{Binding QuickBar[Align3].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Align3}">🎯 三點</ToggleButton>
|
||||
<Separator />
|
||||
<TextBlock Text="旋轉:" VerticalAlignment="Center" Margin="4,0,2,0"
|
||||
ToolTip="對樹面板選取的檔案,繞其中心旋轉 +90°" />
|
||||
<Button Command="{Binding RotateRootCommand}" CommandParameter="X" Padding="6,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding RotateRootCommand}" CommandParameter="X"
|
||||
Visibility="{Binding QuickBar[RotateX].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="選取的檔案繞 X 軸 +90°(先在樹面板點選檔案)">↻X</Button>
|
||||
<Button Command="{Binding RotateRootCommand}" CommandParameter="Y" Padding="6,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding RotateRootCommand}" CommandParameter="Y"
|
||||
Visibility="{Binding QuickBar[RotateY].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="選取的檔案繞 Y 軸 +90°">↻Y</Button>
|
||||
<Button Command="{Binding RotateRootCommand}" CommandParameter="Z" Padding="6,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding RotateRootCommand}" CommandParameter="Z"
|
||||
Visibility="{Binding QuickBar[RotateZ].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="選取的檔案繞 Z 軸 +90°">↻Z</Button>
|
||||
<ToggleButton Style="{StaticResource ModeButton}"
|
||||
ToolTip="拖曳模式:左鍵按住零件沿螢幕平面拖動,放開定位(深度方向先轉視角再拖)"
|
||||
Visibility="{Binding QuickBar[Drag].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
IsChecked="{Binding CurrentMode, Converter={StaticResource ModeConv}, ConverterParameter=Drag}">🖐 拖曳</ToggleButton>
|
||||
<ToggleButton IsChecked="{Binding GizmoEnabled}" Padding="8,4" FontSize="13"
|
||||
<ToggleButton Style="{StaticResource ModeButton}" IsChecked="{Binding GizmoEnabled}"
|
||||
Visibility="{Binding QuickBar[Gizmo].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="三軸操作器:對樹面板選取的檔案顯示 XYZ 箭頭(沿軸移動)與旋轉環(繞軸轉任意角度),每次放開即定位">⊹ 操作器</ToggleButton>
|
||||
<Button Command="{Binding CheckInterferenceCommand}" Padding="8,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding CheckInterferenceCommand}"
|
||||
Visibility="{Binding QuickBar[Interference].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="干涉檢查:2 個以上可見檔案兩兩檢查是否相交(match 判定);無相交時回報最小間隙">🧩 干涉</Button>
|
||||
<Separator />
|
||||
<Button Command="{Binding ClearMeasurementsCommand}" Padding="8,4" FontSize="13"
|
||||
<ToggleButton Style="{StaticResource ModeButton}" IsChecked="{Binding SectionEnabled}"
|
||||
Visibility="{Binding QuickBar[Section].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="開啟/關閉剖面檢視(開啟後下方出現參數列)">✂ 剖面</ToggleButton>
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding ClearMeasurementsCommand}"
|
||||
Visibility="{Binding QuickBar[Clear].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="清除全部量測與標記(Esc = 取消進行中量測/退出模式)">🧹 清除</Button>
|
||||
<Separator />
|
||||
<ToggleButton IsChecked="{Binding UseInch}" Padding="8,4" FontSize="13"
|
||||
<ToggleButton Style="{StaticResource ModeButton}" IsChecked="{Binding UseInch}"
|
||||
Visibility="{Binding QuickBar[Unit].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="切換顯示單位 mm ⇄ inch(既有量測即時換算)">mm ⇄ in</ToggleButton>
|
||||
<Separator />
|
||||
<Button Command="{Binding ExportCsvCommand}" Padding="8,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding ExportCsvCommand}"
|
||||
Visibility="{Binding QuickBar[ExportCsv].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="量測結果匯出 CSV">💾 CSV</Button>
|
||||
<Button Command="{Binding SaveScreenshotCommand}" Padding="8,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding SaveScreenshotCommand}"
|
||||
Visibility="{Binding QuickBar[Screenshot].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="3D 視圖截圖存 PNG(2x 解析度)">📷 截圖</Button>
|
||||
<Button Command="{Binding ExportStepFileCommand}" Padding="8,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding ExportStepFileCommand}"
|
||||
Visibility="{Binding QuickBar[ExportStep].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="把可見檔案(目前對齊位置)匯出成新 STEP 檔 — 對齊插合結果可交接 CAD;不動原始檔">📤 STEP</Button>
|
||||
<Button Command="{Binding ExportStlFileCommand}" Padding="8,4" FontSize="13"
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding ExportStlFileCommand}"
|
||||
Visibility="{Binding QuickBar[ExportStl].IsChecked, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="把可見檔案(目前位置)匯出成 STL 網格檔 — 先設定範圍/格式/單位/精度,確認再匯出">📐 STL</Button>
|
||||
</ToolBar>
|
||||
</ToolBarTray>
|
||||
|
||||
<!-- ─── 剖面參數列(只在剖面開啟時出現)─── -->
|
||||
<ToolBarTray DockPanel.Dock="Top"
|
||||
Visibility="{Binding SectionEnabled, Converter={StaticResource BoolToVis}}">
|
||||
<ToolBar>
|
||||
<ToggleButton IsChecked="{Binding SectionEnabled}" Padding="8,4" FontSize="13"
|
||||
ToolTip="開啟/關閉剖面檢視">✂ 剖面</ToggleButton>
|
||||
<TextBlock Text="✂ 剖面:" VerticalAlignment="Center" Margin="4,0,2,0" />
|
||||
<ComboBox SelectedIndex="{Binding SectionAxisIndex}" Width="60" Margin="4,0"
|
||||
VerticalAlignment="Center" ToolTip="剖切軸向(3點 = 在模型上點 3 點定義任意平面)"
|
||||
IsEnabled="{Binding SectionEnabled}">
|
||||
VerticalAlignment="Center" ToolTip="剖切軸向(3點 = 在模型上點 3 點定義任意平面)">
|
||||
<ComboBoxItem>X</ComboBoxItem>
|
||||
<ComboBoxItem>Y</ComboBoxItem>
|
||||
<ComboBoxItem>Z</ComboBoxItem>
|
||||
<ComboBoxItem>3點</ComboBoxItem>
|
||||
</ComboBox>
|
||||
<Slider Value="{Binding SectionPosition}" Minimum="0" Maximum="100" Width="180"
|
||||
VerticalAlignment="Center" Margin="4,0" ToolTip="剖面位置(沿法向 %)"
|
||||
IsEnabled="{Binding SectionEnabled}" />
|
||||
VerticalAlignment="Center" Margin="4,0" ToolTip="剖面位置(沿法向 %)" />
|
||||
<TextBox Text="{Binding SectionPosition, StringFormat={}{0:F0}}" Width="34"
|
||||
VerticalAlignment="Center" ToolTip="剖面位置 %(0–100,可直接輸入,離開欄位生效)"
|
||||
IsEnabled="{Binding SectionEnabled}" />
|
||||
VerticalAlignment="Center" ToolTip="剖面位置 %(0–100,可直接輸入,離開欄位生效)" />
|
||||
<TextBlock Text="%" VerticalAlignment="Center" Margin="1,0,0,0" />
|
||||
<CheckBox IsChecked="{Binding SectionFlip}" Content="反向" VerticalAlignment="Center"
|
||||
Margin="4,0" ToolTip="切換保留側" IsEnabled="{Binding SectionEnabled}" />
|
||||
Margin="4,0" ToolTip="切換保留側" />
|
||||
<Button Style="{StaticResource QuickButton}" Command="{Binding CloseSectionCommand}"
|
||||
ToolTip="關閉剖面檢視">✕ 關閉</Button>
|
||||
</ToolBar>
|
||||
</ToolBarTray>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
<Version>0.6.0</Version> <!-- 單一版號來源:標題與 publish-winapp 打包資料夾都讀這個 -->
|
||||
<Version>0.7.0</Version> <!-- 單一版號來源:標題與 publish-winapp 打包資料夾都讀這個 -->
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -15,6 +15,9 @@ public class AppSettings
|
||||
public bool WindowMaximized { get; set; }
|
||||
public bool UseInch { get; set; }
|
||||
public List<string> RecentFiles { get; set; } = new();
|
||||
|
||||
/// <summary>快速工具列顯示的按鈕 key 清單;null = 用預設(QuickBarViewModel.Registry)</summary>
|
||||
public List<string>? QuickBarKeys { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>設定讀寫:壞檔/缺檔一律回預設值,儲存失敗靜默(設定不值得讓程式閃退)</summary>
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Windows.Media;
|
||||
using System.Windows.Media.Media3D;
|
||||
using System.Windows.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using HelixToolkit.Wpf;
|
||||
using STPViewer.Models;
|
||||
using STPViewer.Services;
|
||||
@@ -38,6 +39,10 @@ public partial class MainViewModel
|
||||
[ObservableProperty]
|
||||
private bool sectionFlip;
|
||||
|
||||
/// <summary>剖面參數列的「✕ 關閉」按鈕(參數列只在剖面開啟時顯示)</summary>
|
||||
[RelayCommand]
|
||||
private void CloseSection() => SectionEnabled = false;
|
||||
|
||||
// ── 3點自訂剖切平面(SectionAxisIndex == 3,v0.5.0)──
|
||||
private const int CustomAxisIndex = 3;
|
||||
private Vector3D? _customNormal; // null = 尚未定義(等使用者點 3 點)
|
||||
|
||||
@@ -86,6 +86,9 @@ public partial class MainViewModel : ObservableObject
|
||||
public ObservableCollection<ModelNodeViewModel> Roots { get; } = new();
|
||||
public ObservableCollection<MeasurementResult> Measurements { get; } = new();
|
||||
|
||||
/// <summary>快速工具列自訂(選單列有全部功能,快速列只放勾選的常用按鈕)</summary>
|
||||
public QuickBarViewModel QuickBar { get; } = new();
|
||||
|
||||
// ─── 使用者設定(視窗由 MainWindow 處理;VM 管單位 + MRU)─────
|
||||
|
||||
public void LoadSettings(AppSettings s)
|
||||
@@ -94,12 +97,14 @@ public partial class MainViewModel : ObservableObject
|
||||
RecentFiles.Clear();
|
||||
foreach (string f in s.RecentFiles.Where(File.Exists).Take(SettingsService.MaxRecentFiles))
|
||||
RecentFiles.Add(f);
|
||||
QuickBar.Load(s.QuickBarKeys);
|
||||
}
|
||||
|
||||
public void SaveSettingsInto(AppSettings s)
|
||||
{
|
||||
s.UseInch = UseInch;
|
||||
s.RecentFiles = RecentFiles.ToList();
|
||||
s.QuickBarKeys = QuickBar.ToKeys();
|
||||
}
|
||||
|
||||
private void TouchRecent(string path)
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace STPViewer.ViewModels;
|
||||
|
||||
/// <summary>快速列單一按鈕的顯示開關(選單「快速列 → 自訂按鈕」的 checkbox 項)</summary>
|
||||
public partial class QuickBarItemViewModel : ObservableObject
|
||||
{
|
||||
public string Key { get; }
|
||||
public string Label { get; }
|
||||
public bool Default { get; }
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isChecked;
|
||||
|
||||
public QuickBarItemViewModel(string key, string label, bool @default)
|
||||
{
|
||||
Key = key;
|
||||
Label = label;
|
||||
Default = @default;
|
||||
isChecked = @default;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 快速工具列自訂:所有功能都在選單列,快速列只放使用者勾選的常用按鈕。
|
||||
/// XAML 以索引子綁定:Visibility="{Binding QuickBar[Point].IsChecked, Converter=…}"。
|
||||
/// 勾選狀態隨 settings.json(QuickBarKeys)保存;null = 用預設。
|
||||
/// </summary>
|
||||
public partial class QuickBarViewModel : ObservableObject
|
||||
{
|
||||
/// <summary>註冊表 = 快速列順序 + 選單顯示名 + 是否預設顯示(一般 user 常用)</summary>
|
||||
private static readonly (string Key, string Label, bool Default)[] Registry =
|
||||
{
|
||||
("Import", "📂 匯入", true),
|
||||
("Recent", "▾ 最近檔案", true),
|
||||
("ZoomAll", "🔍 全覽", true),
|
||||
("ViewIso", "視圖:等角", true),
|
||||
("ViewFront", "視圖:前", false),
|
||||
("ViewTop", "視圖:上", false),
|
||||
("ViewRight", "視圖:右", false),
|
||||
("Ortho", "正交投影", true),
|
||||
("Point", "📍 點", true),
|
||||
("Distance", "📏 距離", true),
|
||||
("Edge", "📐 邊", false),
|
||||
("Face", "⬛ 面", false),
|
||||
("Circle", "⭕ 圓", true),
|
||||
("Angle", "∠ 角度", true),
|
||||
("FaceDistance", "⇔ 面距", false),
|
||||
("Align", "🎯 兩點對齊", false),
|
||||
("Align3", "🎯 三點對齊", false),
|
||||
("RotateX", "旋轉 ↻X", false),
|
||||
("RotateY", "旋轉 ↻Y", false),
|
||||
("RotateZ", "旋轉 ↻Z", false),
|
||||
("Drag", "🖐 拖曳", false),
|
||||
("Gizmo", "⊹ 操作器", false),
|
||||
("Interference", "🧩 干涉", true),
|
||||
("Section", "✂ 剖面", true),
|
||||
("Clear", "🧹 清除量測", true),
|
||||
("Unit", "mm ⇄ in", true),
|
||||
("ExportCsv", "💾 匯出 CSV", false),
|
||||
("Screenshot", "📷 截圖", false),
|
||||
("ExportStep", "📤 匯出 STEP", false),
|
||||
("ExportStl", "📐 匯出 STL", false),
|
||||
};
|
||||
|
||||
private readonly Dictionary<string, QuickBarItemViewModel> _byKey;
|
||||
|
||||
/// <summary>依快速列順序的全部項目(選單自訂清單用)</summary>
|
||||
public IReadOnlyList<QuickBarItemViewModel> Items { get; }
|
||||
|
||||
public QuickBarViewModel()
|
||||
{
|
||||
Items = Registry.Select(r => new QuickBarItemViewModel(r.Key, r.Label, r.Default)).ToList();
|
||||
_byKey = Items.ToDictionary(i => i.Key);
|
||||
}
|
||||
|
||||
/// <summary>XAML 索引子綁定入口:QuickBar[Point].IsChecked</summary>
|
||||
public QuickBarItemViewModel this[string key] => _byKey[key];
|
||||
|
||||
/// <summary>套用保存的勾選清單;null = 維持預設(含未知 key 容錯:新版本新增按鈕用預設值)</summary>
|
||||
public void Load(List<string>? visibleKeys)
|
||||
{
|
||||
if (visibleKeys is null) return;
|
||||
var set = new HashSet<string>(visibleKeys, StringComparer.Ordinal);
|
||||
foreach (QuickBarItemViewModel item in Items)
|
||||
item.IsChecked = set.Contains(item.Key);
|
||||
}
|
||||
|
||||
/// <summary>目前勾選清單(存 settings.json)</summary>
|
||||
public List<string> ToKeys() =>
|
||||
Items.Where(i => i.IsChecked).Select(i => i.Key).ToList();
|
||||
|
||||
[RelayCommand]
|
||||
private void ResetDefaults()
|
||||
{
|
||||
foreach (QuickBarItemViewModel item in Items)
|
||||
item.IsChecked = item.Default;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user