Skip to content

命中高亮與導覽 ​

命中標成什麼樣、目前那一處怎麼分辨、怎麼一處一處走過去:視覺契約跨所有顯示命中的表面, 算位置與狀態各一份。產品與 provider 契約見 SQL Search,其餘視覺語言見 UI 準則。

四份職責 ​

每一個顯示命中的表面都走同一條路,各功能只決定拿什麼去找;併段、上限、提示與接線各只有一份, 改一處兩個工具窗一起變。

  • 找(各功能):SQL Search 是 Ssms22/Search/SqlSearchDefinition.cs 的 SqlSearchDefinitionHighlight,走 SearchHit.Matches——併進來的那幾筆全部算——並用 TextMatcher.FindAll 找出片段在定義裡的每一次出現:一個資料行名稱在 CREATE TABLE 裡出現 一次,在 sp_addextendedproperty 裡還會再出現一次。SQL Memory 用清單那一輪的比對器 (SqlMemoryQuery.Matcher)找 SQL 全文,不另寫比對:清單認得的那一列,預覽就標得出來。
  • 併與截:Core/Matching/MatchHighlights.cs。重疊或緊貼的區段併成一段(打 Due 而表上同時有 Due 與 DueDate),文件那一層要由小到大且不重疊。上限 Maximum 落在標記上不落在比對上, 超過時截斷;MatchHighlightSet.Notice 決定要說的那一句(Search 走降級通知,Memory 在預覽狀態列), 少標了永遠先說——少標了卻不說, 使用者按到最後一處就以為看完了。一處都沒有時說什麼由功能給(Search 是位置對不上定義, Memory 是收藏只靠名稱或說明命中)。
  • 狀態:Core/Matching/MatchCursor.cs。有幾處、現在第幾處、上下一處與環繞收在一份純邏輯裡; 散到每一個表面各寫一次的症狀是其中一個按到最後一處就不動了,而另一個會捲回文件開頭。
  • 呈現:指令碼是 SqlScriptDocument 的兩級資源(ScriptResource.Highlight 與 HighlightCurrent),清單列是 SqlHighlightText;SqlMatchNavigator 畫那兩顆按鈕與「3 / 7」, SqlMatchNavigation 把它接到預覽的 SQL 檢視、放上工具列並決定第一處的捲動。

視覺契約 ​

顯示命中的表面每一個都照這一份,不分預覽或清單。

  • 命中自成一組色票,不借 ThemeBrush.AccentBackground:那一份同時是搜尋框那幾顆開關 「開著」的底,共用的話一邊為了對比調整、另一邊跟著變;而且它是 Tint(0.12) 並在對比不足時 把 alpha 逐次折半,退到幾乎看不見——「有沒有標出來」正是使用者唯一要從這裡讀到的事。
  • 第二級屬於走得動的表面:「哪幾處對上了」與「我現在在第幾處」是兩個問題,而第二個問題 只有配了導覽的表面答得出來——目前是 SQL Search、SQL Memory 的預覽與結構預覽的指令碼分頁。清單列與資料格只有第一級:導覽走的是定義全文的位置, 與那一列上的名稱、資料行不是同一組座標,硬對應會把「目前」指到不相干的那一段。
  • 兩級都蓋掉底下的語法著色。要留住著色就得讓底色與最淡的那個分類色維持 4.5:1,而校正 只能把底色往表面推——推完就是一層幾乎看不見的薄色,實機上那一版看起來只剩粗體。留住著色 與一眼看得出來互斥,而使用者要從這裡讀到的是後者;分類色在命中那幾個字上讀不到並不影響 判讀,它們周圍仍然有色。
  • 字重再分一級(一般 SemiBold、目前 Bold),狀態就不是只靠顏色表達。反過來只靠字重也不行, 那正是高亮退成薄色之後剩下的東西,而它在介面字型上差得太少。
  • 底色、字色與兩級的門檻都在文字標記;這一層只說命中有兩級、哪一級配哪一個 強度。基準由各表面自己給(工具窗是 ListBackground,指令碼借的是編輯器底色),推導只有 一份——各寫一份的症狀是同一個搜尋字在同一個視窗的兩塊看起來不是同一件事。

兩級分不分得出來只有眼睛驗得了:Light/Dark/高對比各一次,深色主題另加 150% DPI; 彩色深色主題(月光、神祕森林、辣紅)要單獨看過,強調色在那幾套上本來就接近編輯器底色。

換「目前」是換那幾個 Run 的資源鍵,不重建文件:重建一次幾千行的指令碼會讓每按一次都掉影格, 而且選取與捲動位置會一起丟掉。一處命中可能跨好幾個 Run(高亮切的是原文位移,著色切的是 詞法單元),所以 Build 交出的是「每一處的那幾個 Run」而不是一個錨點。

自動捲動只發生在換一列的第一次:整份定義從頭顯示而命中在幾百行之下時,使用者看不出自己 選的這一筆為什麼在清單上。之後的每一次捲動都是他自己按的。

沒有鍵盤捷徑。 F3/Shift+F3 在 SSMS 上是查詢視窗的「找下一個」,宿主在 WPF 看到按鍵 之前就把它吃掉了(命令路由的 pretranslate),工具窗上的 PreviewKeyDown 一次都不會跑到—— 那一版寫進 Tooltip 的提示按下去毫無反應,而使用者會以為整個導覽壞了。真要接得住得去註冊 宿主的命令與鍵繫結,那是另一件事。工具窗只攔 Ctrl+F(跳到搜尋框)。

導覽排在工具列最前面,與後面的命令之間是那條共用的群界線(CreateGroupDivider),沒有命中時 整組連同那條線一起收起。顯示換行靠工具列右緣(CreatePreviewToolbar):它只改怎麼看,不和命令排在一起。

那顆複製鈕複製的是畫面上這一份定義,不是名稱:使用者按預覽裡的複製,要的是他正在看的 那段結構描述;名稱在清單的右鍵選單上(「複製名稱」),那裡才是「這一列是什麼」的位置。 只提供片段的來源複製不出結構描述,所以它與換行一樣,等定義載進來才開——一顆複製得到半句話 的按鈕比沒有那一顆更難解釋。換行是開關不是按鈕(CreateIconToggle):它按下去之後一直 維持著,而維持著的狀態要在那一顆自己身上看得出來,否則使用者只能去看內容猜, 而一份本來就不長的指令碼看不出差別。

以 Apache-2.0 授權條款發布 · 專為 SSMS 22 設計