視窗骨架
停靠工具窗(SQL Memory、SQL Search)與之後的視窗共用的骨架與主從區契約。清單列見 清單列,視覺語言見 UI 準則,元件的唯一出處見 平台共用元件。
骨架
視窗從同一個入口組裝,三塊固定:
- 工具列
Dock=Top:上層是範圍(SqlFilterBar:filters 與分段開關,窄版依群組換行), 下層是共用的SqlInputRow(見下),貼著清單。先決定「在哪裡找」再打「找什麼」,打字的地方 離結果最近;多選時蓋在輸入列上的選取工具列也因此正好在清單上面。工具窗沒有原生 Titlebar, 分頁列(有的話)之下直接是工具列。 - 選取工具列:多選模式中蓋在輸入列同一格(
SqlSelectionBar.Slot),高度相同, 被蓋住的輸入列停用、Tab 走不進去:多選時改搜尋字會清空勾選。內容是 ✕、「已選 N 筆」 (全部符合時接一段淡色的已載入筆數)、全選,右側是動作按鈕,破壞性動作前一條群界線;按鈕照SqlSelectionAction描述畫,工具列不認得任何一個動作。背景讀取的進度也在這一格:筆數換成進度,全選與動作 讓給「取消」。收起時焦點若在工具列上就交回清單的焦點列。 - 沒有已選條件列:哪幾個維度有條件由篩選按鈕自己說(摘要,加上強調底框,見 篩選)。另起一列 chip 的那一版與按鈕摘要說的是同一件事,條件一設就把 清單往下推一列,而清除與調整本來就在面板裡。
- 主從區:取剩餘空間。
- 清單頁尾(
SqlListPager,清單的最後一項):筆數、部分結果、完整度與續頁;文案與語氣圖示由各清單的 模型給(SqlListFooter)。跑得久的工作在清單上方另有一條進度(SqlProgressStrip)。效果在視窗外的 動作結果一律走通知。 - 狀態列:SQL Search 沒有;SQL Memory 的平時
Collapsed,只留說明畫面的那幾句(讀取失敗、停用)。
輸入列與範圍列
SqlInputRow 是輸入列的唯一一份,SQL Memory 與 SQL Search 共用;它只定一條界線, 三種東西各有各的位置:
| 這一顆在做什麼 | 放哪裡 |
|---|---|
| 修飾這個字串怎麼比(大小寫、全字、清除) | 搜尋框裡面(CreateInputBar) |
| 作用在這一份結果(排序、重新整理) | 搜尋框外面的右緣 |
| 縮小搜尋範圍(伺服器、資料庫、種類、比對位置) | 上層的 SqlFilterBar |
套用查詢視窗的連線屬於範圍:它一次換掉伺服器與資料庫兩個條件,是那兩顆的捷徑,所以兩個工具窗 都放在範圍列伺服器的左邊(CreateEditorConnectionButton),Tooltip 打開那一刻才寫出會套到哪一條。 放在搜尋框右緣的那一版,讓人以為它作用在搜尋字串上。它是一次性的動作,不是一種範圍狀態:兩邊都 把兩個篩選取代成當下那一台與那一個(SqlConnectionScope.Apply),之後切分頁、換連線都不再跟著走; 下拉裡也沒有「查詢視窗」這個選項,只列目前能用的名稱。查詢視窗沒有連線時兩邊都不動範圍、 回報同一句。用詞一律是「查詢視窗」(SqlEditorConnectionText),不叫「目前連線」:選了別台 伺服器之後,「目前連線」讀起來像是那一台。
輸入框吃剩餘寬度並保留 MinInputWidth;右緣那幾顆固定寬,收起的那一顆連它前面那一段 間距一起讓開。三種混排在同一個地方的症狀是使用者分不出哪一顆會改變「找到什麼」、 哪一顆只改變「怎麼看這一份」。
框裡那幾顆常駐可見,「開著」必須在那一顆自己身上看得出來,所以走 CreateToggleStyle:強調底加 強調框,與核取方塊的「打勾」同一組色。沿用分段開關那一份的那一版看不出狀態——它的選取 底色刻意等於 ListBackground,而搜尋框的底色正是它,疊上去只剩一圈髮絲線。
幾塊之間的間距由骨架這一層給,工具列、主機訊息與狀態列不自己帶 margin;階與理由見 UI 準則的版面層級。各自帶的那一版,會收起的那一塊一收起,工具列與清單之間 就一點間距都不剩——而收起正是它的常態。
主從區與 Preview 標頭
寬到門檻轉左右分割,否則上下。轉向在 MeasureOverride 決定,等到排版才換會閃一次舊版面; 門檻留 24–40 DIP hysteresis,臨界寬度不得反覆跳。兩個方向的拖曳比例分開記,換向再換回來 仍是使用者拖過的那一份。Resize 不重查資料、不重建結果集合,不改選取與捲動位置。
兩個方向的預設相反:上下是清單 3:Preview 2,左右是 2:3。清單列的寬度有上界(名稱截在 RowNameMaxWidth,其餘固定寬或可省略),再寬只是右邊空著;SQL 沒有,窄一點就是每一行都折。
Preview 標頭(開關與摘要)分兩態:
- 展開時標頭屬於 Preview,貼在它上緣:上下分割橫跨整列(那裡本來就在清單與 Preview 之間), 左右分割只屬於右邊那一欄,不跨到清單上方——管右邊那一塊的開關出現在清單左上角, 就是它不該在的位置。也不能放進中間那欄,那裡只有 5 DIP 寬。清單與分隔線跨過標頭那一列。
- 收合時 detail 與 splitter
Collapsed,標頭退化成貼在清單下緣(上下分割)或右緣 (左右分割)的單列把手。開關不得跟著 detail 一起收掉,否則收合後再也展不開。
兩態都要有 AutomationName,並隨狀態換成「收合預覽/展開預覽」。
狀態表面
載入、空、錯誤、無權限與不完整五種狀態只有一份實作,疊在同一塊內容上,不各占一塊版面。沒有選取時 Preview 的 摘要與操作一起收起:膠囊樣板繫不到值仍會把底畫出來,那塊沒有字的灰方塊看起來像是一筆載不出名稱 的結果。錯誤與無權限 走同一個出口,文案分成「這一輪讀不到」與「權限不足」。一列都沒有時清單頁尾讓開,同一句話 不在畫面中央與下緣各說一次;清單上還留著列時失敗寫在頁尾(Memory 是狀態列),不遮住讀得到的那幾筆。
兩個抬頭的下一步完全不同(重試或換條件 vs. 去要權限),所以「權限不足」是一句斷言, 換抬頭的門檻只有一條:讀不到的來源每一個都回報得出結構化的權限原因。其中之一就換的話, 使用者照抬頭去要了權限,那個連不上的來源下一輪還是讀不到,而畫面上看不出他要錯了東西; 反過來一律說「這一輪讀不到」的那一版,則會讓真的缺權限的人一直重試。SQL Search 那一邊 由 SearchUnavailableKind 帶著走,見 完整度與進度。 結果不完整而一列都沒有時是第五種狀態 Incomplete:抬頭照樣說沒有相符項目,但掛警示圖示。
design token
字型、字級、間距、圓角、動畫長度與語意色只進 SqlAssistChrome(含 partial)與 ThemePalette/ThemeColorMath,顏色繫結 VsThemeBrushes 的動態資源。不得另開 ResourceDictionary,不得在功能目錄複製樣板或硬寫 RGB。間距也是 token,排版器裡那種 自己宣告的 RowGap 常數一樣回到這裡——複製兩份的下場是調了其中一份,兩層工具列的間距 從此不一樣。
動畫與延遲
| 分級 | 資產 | 長度 |
|---|---|---|
| 內容表面出現 | PlayAppear | 120 ms 淡入 |
| 浮動預覽長出/縮回/原地換 | PlayEnter/PlayExit/PlaySwap | 圓點長成膠囊再攤開,內容沒到先停在膠囊(PreviewReveal);內容照 SurfaceMotion;縮回不回彈 |
| 列的揭露 | CardEnterDuration/CardExitDuration | 180/140 ms |
| 狀態回饋 | UsageBadgePop、SearchStatusPop(含已選筆數與動作完成的打勾) | 240 ms |
| 動作完成的打勾停留 | SelectionDoneHold | 1200 ms,動畫關閉時照樣換圖示 |
| 列操作的揭露 | RowActionRevealDuration | 120 ms 淡入+6 DIP 滑入 |
| 選取工具列進出 | 同上(PlaySelectionBar) | 可中途反向;勾選欄不另播,見清單列 |
| 展開/收合箭頭轉向 | ChevronTurnDuration | 140 ms 轉到位,可中途反向 |
| 主從區轉向 | 無,也不要加 | 轉向在 MeasureOverride,加動畫會抖 |
三級都受全域動畫設定控制。debounce 走同一張共用常數表:Search 搜尋 200、 預覽 220、Cleanup 估算 250、Memory 搜尋 300 ms。
元件邊界
- Badge 與按鈕型 Chip 是不同 primitive,共用尺寸、圓角、spacing、狀態色與 icon slot,不共用互動語意。
- 篩選列、兩級分隔線、過濾面板與展開箭頭見篩選。
- 兩個 Browser 不合成通用元件:外觀共用,領域語意與 command 留在各 feature。
驗收
保留取消/generation guard、背景工作、每批 40 筆與 recycling virtualization。禁用每列陰影、 模糊與複雜動畫;主題/DPI 切換後不殘留舊 brush 或裁切 icon。 版面、狀態表面與分隔線的逐項斷言在 WPF 元件測試裡,不在這裡重列一份會過時的清單。 文件只留眼睛才看得出來的:Light/Dark/Blue 與 100/150/200% DPI、300 DIP 下每一組控制 仍在列內、窄版降級與 overflow,以及展開態的 Preview 開關留在右欄。間距另看兩態:選取工具列 進出、篩選列換到第三列,工具列整塊與清單之間都是同一段。