Skip to Content
Plugin 開發nxlayout 工具與視覺化編輯器

nxlayout 工具與視覺化編輯器

前面幾章的 .nxlay 面板設計檔,除了用文字編輯器手寫,PDK 還附兩個工具幫你做:

工具是什麼在 PDK 的位置
nxlayout.exe命令列工具:驗證 .nxlay、求解版面、輸出 C 標頭tools\x64\、tools\x86\(旁邊的 nxlayout_core.dll 要一起放)
nxlayout_editor.exe視覺化編輯器:拖曳排版、即時預覽兩個版本、驗證、輸出標頭、AI 輔助editor\

不要和主程式的 F9「版面配置器」搞混。 F9 是使用者在主程式裡決定「畫面上放哪幾個面板、怎麼分割」用的 (見檢視選單),它排的是主程式的面板配置。 這一章的編輯器是你(Plugin 作者)設計自己那個 Widget 面板裡面有哪些控制項用的,它產出 .nxlay 檔,跟主程式的設定無關。

啟動與主視窗

直接執行 nxlayout_editor.exe。PDK 附的是自帶執行環境的單一檔案版本,不需要另外安裝 .NET。

第一次開啟時中間是空的,有三個入口:New blank panel(新空白面板)、Import from existing .h…(從既有的 .h 匯入)、Open sample(開範例)。

主視窗是可停靠的窗格,View 選單可以開關,Reset Layout to Default 還原預設排列:

窗格用途
Toolbox15 種控制項型別的清單,拖到畫布上新增
Outline目前面板所有控制項的清單(ID、型別、標籤、寬度狀態)
Canvas主編輯區
Inspector選取項目的屬性表
Error List驗證錯誤的即時清單
Preview視窗版/終端機版兩種真實渲染的預覽
AI用自然語言請外部 AI 產生或修改面板(與 Inspector 同一組頁籤)
nxlayout 編輯器的主視窗:左邊 Toolbox 與 Outline,中間 Canvas
左:Toolbox 與 Outline;中:Canvas。這是 hello_ic 第四步的面板(點圖看完整原圖)

Canvas 畫的不是示意圖,是求解器的真實輸出:編輯器與 nxlayout --solve、與主程式用的是同一份排版程式,所以你在畫布上看到的位置與工具算出來的逐格相同。 標題列的 * 表示有未存檔的變更;意外關閉後重開,會問你要不要復原上次沒存的內容;檔案在編輯器外被改動時也會問你要重新載入還是保留你的版本。

建立新面板:空白、範本精靈、匯入

三種起手方式:

  1. New blank panel(File > New,Ctrl+N):輸入面板尺寸,建立一個沒有控制項的新文件。
  2. New from template(精靈):選一個內建範本(表單、儀表板、工具列三種),調整面板的寬與高,按 Create。只有這兩個參數。
  3. Import from existing .h…:把一份 nxlayout --emit-header 產生的 .h 讀回來還原成可編輯的面板。這是從既有 C 程式進入編輯器的唯一路徑。
範本精靈對話框:Template、Panel width、Panel height、Create、Cancel
範本精靈:選範本、設面板尺寸(點圖看完整原圖)

Toolbox:新增控制項

Toolbox 列出全部 15 種型別。新增有兩種方式:

  • 拖曳:把項目拖到 Canvas 上放開,控制項出現在放開位置對應的格子。
  • 雙擊:雙擊項目,控制項附加在面板目前內容的最下面一列。

新增出來的控制項預設值已經滿足驗證規則,例如 METER/SPIN/CHART 已填 NumMax = 100、GROUPBOX 已勾 Decoration 且 H = 5、 SEPARATOR/TEXTBOX/DROPDOWN 已有 Weight = 1。各型別的用途與欄位見Widget 型別詳解。

Toolbox 新增前,面板只有兩個控制項
新增前:Outline 有 2 個控制項(點圖看完整原圖)
新增一個 Text Box 之後,Outline 變成 3 個
新增後:Text Box 出現在 Canvas,Outline 變成 3 個(點圖看完整原圖)

Canvas:選取、移動、調整、對齊

  • 選取:單擊選一個;在空白處拖曳框選多個。
  • 移動:拖曳選取中的控制項,改變它的 X 與 Y。
  • 調整尺寸:單選一個控制項時,右下角出現實心藍色控點。水平拖曳改 MinW,垂直拖曳改 H。 MaxW 與 Weight 拖不到,只能在 Inspector 輸入。
  • 複製/貼上/刪除:Ctrl+D 複製選取項目、Ctrl+C/Ctrl+V 剪貼簿複製貼上、Delete 刪除。刪除不重新編號:被刪掉的 WidgetId 就空出來,不會被後來新增的控制項沿用。
  • 復原/重做:Ctrl+Z/Ctrl+Y。
  • 對齊與均分(Edit 選單,作用在多選的控制項):靠左、靠右、靠上、靠下、水平置中、垂直置中、水平均分、垂直均分。
  • 縮放:畫布會自動把面板放大填滿視窗(整數倍),只影響顯示;求解永遠用面板的 RefW/RefH。
在畫布上單選一個按鈕,出現選取框
單選:選取框與右下角控點(點圖看完整原圖)
用對齊功能移動按鈕之後的畫布
對齊之後的畫布(點圖看完整原圖)

Inspector:每一個屬性

Inspector 是右邊的屬性表,選了控制項顯示控制項的屬性,沒選任何控制項時顯示整個面板的屬性。 底下的說明列會顯示目前選中那個屬性的簡短說明。改了值,Canvas、Outline、Preview 立刻跟著變。

Inspector 只顯示對該型別有意義的屬性。 沒出現的屬性就是那個型別用不到。 下面每一項都寫了:作用、哪些型別看得到、範圍與意義、怎麼調整(輸入=在格子裡打數字或文字,下拉=從清單選,勾選=True/False,拖曳=在 Canvas 上直接拖)。

面板層級(沒選任何控制項時)

Inspector 顯示面板層級屬性 RefW、RefH、Guides、GuideWeight、GuideMaxW
面板層級的屬性(點圖看完整原圖)
屬性作用與意義怎麼調整
RefW參考寬度(抽象格):這份版面是以多寬設計的。編輯器與 nxlayout --solve 預設就用它當面板寬。不要留 0:留 0 的話生存掃描會退回 20 格寬輸入
RefH參考高度(抽象格)。超過這個高度的列會被求解成不可見,Outline 會標成「一定隱藏」輸入
Guides欄導引線在參考寬度下的 x 位置(抽象格)。空的代表沒有導引線,控制項只靠 X 定位。最多 8 條集合編輯(點右邊 (Collection) 的按鈕新增、刪除、改值)
GuideWeight每條導引線那一欄的長大權重,0 代表該欄固定寬。必須是空的,或長度剛好等於 Guides集合編輯
GuideMaxW每一欄的寬度上限(抽象格),0 代表沒有上限。必須是空的,或長度剛好等於 Guides集合編輯

導引線是進階功能:宣告了導引線之後,同一欄的控制項可以綁到同一條線,上下對齊,並且整欄一起依權重長大。不需要就不要宣告。

控制項層級

下面這張表列出全部的控制項屬性,以及各型別哪些會出現:

屬性出現在範圍與意義
WidgetId全部面板內唯一的識別碼,也是 .nxlay 裡 [w.N] 的 N。C 端的事件與 SetWidgetProp 都靠它辨認。不能重複
Type全部控制項型別,決定其他哪些屬性有意義
Y全部列座標(抽象格,0 起算)。Y 相同的控制項在同一列。宣告順序中 Y 不可遞減
X全部欄座標(抽象格)。同一列裡後一個要放在前一個的 X + MinW 之後。就算綁了導引線也要填成與該導引線設計時位置相符,否則常會觸發「同列重疊」
MinW全部最小寬度(抽象格)。面板窄到放不下就會隱藏(見Widget 模式深入)
MaxW全部長大上限(抽象格),0 是不設上限。非 0 時必須不小於 MinW
Weight全部分配剩餘寬度的權重,0 是固定寬(永遠等於 MinW)
HTABLE、GROUPBOX、CHART、IMAGE高度(抽象格)。0 是自動(延伸到下一列或面板底)。GROUPBOX 一定要明確給。TABLE 的高度其實由「到下一列的距離」決定,H 對它沒有作用
Label除了 IMAGE、CHART 以外全部標籤/按鈕文字/標題,最多 31 個字元。TEXTBOX、SPIN、METER、CHOICE、FILEPICK、SEPARATOR 雖然能填,但畫面上不會畫出來
ItemCountDROPDOWN、CHOICE選項數,0~8。選項文字由 C 端以 SetWidgetProp 的 NX_WP_ITEMS 設定
NumMinMETER、SPIN數值下限(有號整數)
NumMaxMETER、SPIN數值上限(有號整數)。不可為 0,而且要大於 NumMin
NumStepSPIN每次增減量,0 視為 1
AuxIMAGE、FILEPICKIMAGE 的圖檔名,或 FILEPICK 的篩選字串(例如 *.bin)。不能含 \、/、:、..
Optional全部勾選=空間不夠時可以被隱藏(由後往前,與其他 Optional 控制項一起)
Decoration全部勾選=純裝飾:不可聚焦、不受「跨列重疊」規則限制、畫在最底層。實務上只有 GROUPBOX 需要
ActivatableMETER、CHART、IMAGE、LABEL、VALUE勾選=這個原本唯讀的控制項可聚焦、可以被點,並送 ACTIVATED 事件。其他型別不合法,所以 Inspector 直接不顯示這一項
XGuide面板宣告了 Guides 時,全部這個控制項那一段從哪條導引線開始;(unbound) 是不綁。下拉選單會列出 guide 0 @ x=0 這樣的選項。這只是備用方式,主要做法是在 Canvas 上拖曳吸附

哪些用拖曳、哪些只能輸入: X、Y 可以拖曳移動;MinW 與 H 可以拖右下角控點; MaxW 與 Weight 沒有拖曳手勢,一定要在 Inspector 輸入。 其餘屬性都在 Inspector 輸入、下拉或勾選。

沒有出現在 Inspector 的欄位:.nxlay 裡的 flags=DISABLED、flags=PASSWORD、flags=ALIGN_RIGHT, 以及 preview_* 預覽用欄位,編輯器沒有對應的輸入格。要用它們請直接在 .nxlay 文字裡寫,編輯器重新存檔時會保留。 另外 CHART 的 NumMin/NumMax(縱軸範圍)與 Label 也不在 Inspector 裡,同樣要直接改文字。

各型別實際看到的屬性長什麼樣:

Button 的 Inspector:沒有 H、NumMin 等
Button:只有共通屬性與 Label(點圖看完整原圖)
Dropdown 的 Inspector:多了 ItemCount
Dropdown:多了 ItemCount(點圖看完整原圖)
Spin 的 Inspector:多了 NumMin、NumMax、NumStep
Spin:多了 NumMin、NumMax、NumStep(點圖看完整原圖)
Group Box 的 Inspector:多了 H,Decoration 為 True
Group Box:多了 H,Decoration 預設為 True(點圖看完整原圖)
Value 的 Inspector:多了 Activatable
Value:多了 Activatable(LABEL、VALUE、METER、CHART、IMAGE 才有)(點圖看完整原圖)
XGuide 下拉選單列出各條導引線
面板有導引線時多出 XGuide,用下拉選單綁定(點圖看完整原圖)

改屬性的效果:下面兩張是把按鈕的 MinW 從 8 改成 20 的前後對照,Canvas 與底下的 Preview 都跟著變寬。

MinW 為 8 時的整個編輯器
調整前:MinW = 8(點圖看完整原圖)
MinW 改為 20 之後的整個編輯器
調整後:MinW = 20,Canvas 與 Preview 都變寬了(點圖看完整原圖)

Preview:視窗版與終端機版雙預覽

Preview 窗格有兩個選項:GUI(視窗版的真實 GDI 渲染)與 TUI(終端機版的真實字元格渲染)。兩者都是主程式的渲染器輸出,不是編輯器自己模擬的示意。 每個預覽同時並排畫幾種面板寬度(生存掃描),讓你在改版面前就看到窄面板下哪個控制項會消失。

Preview 的 GUI 模式,三種寬度並排
GUI 預覽:三種寬度並排(點圖看完整原圖)
Preview 的 TUI 模式,三種寬度並排
TUI 預覽:同一份版面在終端機版的樣子(點圖看完整原圖)

Error List:驗證錯誤

每次編輯,編輯器都用和 nxlayout --solve 同一套驗證重新檢查整份文件,違規的地方列在 Error List:

欄位內容
Rule違反的規則名稱,例如 x_overlap、y_order、num_range
Widget出問題的控制項 WidgetId
Message說明(英文)

雙擊一列會選取該控制項。 驗證只回報第一個違規,修好它才會看到下一個。

Error List 顯示一筆 x_overlap 錯誤
兩個控制項在同一列重疊:x_overlap(點圖看完整原圖)

一共有 11 條版面規則,加上 .nxlay 文字本身的語法錯誤(顯示為 parse_error):

規則名稱意思
count_limit一個面板最多 32 個控制項
y_orderY 在宣告順序中不可遞減
x_overlap同一列相鄰的兩個控制項不可重疊:後一個的 X 要大於等於前一個的 X + MinW
y_overlap不同列、水平範圍相交的控制項不可在垂直方向重疊(Decoration 的除外)
guide_order同一列裡 XGuide 要依宣告順序嚴格遞增
guide_dup同一列裡兩個控制項不可綁同一條導引線
constraintMaxW 非 0 時不可小於 MinW;XGuide 不可超出導引線數
num_rangeNumMax 非 0 時要大於 NumMin;METER/SPIN 的 NumMax 不可為 0
id_boundsWidgetId 不可重複;ItemCount 不可超過 8
groupbox_auxGROUPBOX 的 H 不可為 0;Aux 不可含 \、/、:、..
activatableActivatable 只限 METER/CHART/IMAGE/LABEL/VALUE,且不能與 Decoration 並用

存檔前 Error List 要是空的:有違規時編輯器拒絕存檔(會跳出 Could not save - the current document is not in a valid state 的訊息)。 所以你不會存出一份驗證不過的 .nxlay。不過拿去給 Plugin 用之前,仍建議用 nxlayout --solve 再獨立驗一次,因為檔案之後可能被手改過。

AI 面板:用自然語言產生或修改面板

AI 面板請外部的 AI 服務依你的描述產生一份 .nxlay。它接受任何相容 OpenAI Chat Completions 格式的端點; 本站的截圖是接到本機執行的 Ollama(http://127.0.0.1:11434/v1)拍的,模型名稱照實顯示在畫面上,你可以換成任何相容的端點。

AI 面板的設定與請求區
AI 面板:Endpoint、Model、API key、尺寸與請求內容(點圖看完整原圖)

設定:填 Endpoint、Model、API key。API key 用 Windows DPAPI(目前使用者範圍)加密後才存檔,只有同一個 Windows 使用者帳號在同一台機器上解得開; Endpoint 與 Model 不是機密,明文存放。也可以用環境變數 NXLAYOUT_AI_API_KEY 提供金鑰(有設就優先使用,不會寫到磁碟)。設定都存在 %APPDATA%\NxLayoutEditor\,不會進 .nxlay、也不會進你的專案。

用法:

  1. 設 ref_w、ref_h(面板尺寸),在 Request 描述你要的面板。可以附圖(例如手繪草圖),下方顯示已附幾張。
  2. 想改現有的面板而不是新做一份,勾 Modify current layout:AI 會拿到目前的版面當基礎。
  3. 按 Generate。第一次使用會跳出同意視窗,說明你的請求(以及目前的版面與附圖)會送給你設定的外部 AI 服務,送出去等於公開,可能被對方保存或索引。同意後才會送。
  4. 每次送出前,按鈕下方都有一行摘要:Will send: ... lines of current layout, N image(s), N characters of prompt,明確寫出要送什麼。Show full request 可以展開看完整的請求內容。
第一次使用時的同意視窗
第一次使用的同意視窗(點圖看完整原圖)

結果:AI 的輸出會先驗證(要通過和 Error List 一樣的規則)。沒通過就把錯誤訊息回饋給 AI 自動重試,預設最多 3 次;還是不行就顯示失敗。 連線錯誤、逾時這類失敗不會自動重試(重試也不會變好,還會白花你的 token),按 Retry 由你決定。

驗證通過的結果是一份草稿,標示 AI draft - not adopted,畫面上會顯示這次用了多少 token;此時它還沒有進到你的文件:

AI 草稿:Adopt、Discard、Retry 三個按鈕與用量
草稿:Adopt 採用、Discard 丟棄、Retry 重來(點圖看完整原圖)
  • Adopt:採用,草稿變成你的文件內容,這是一筆可以復原(Ctrl+Z)的編輯。
  • Discard:丟掉,什麼都沒改。
  • Retry:用同樣的請求再產生一次。

AI 面板從不自己寫檔,採用之後你仍要自己存檔,存檔前也一樣要通過驗證。

Modify 模式的結果
Modify 模式:在現有面板上要求加一個控制項(點圖看完整原圖)
採用之後的畫布
採用之後:新控制項出現在畫布與 Outline(點圖看完整原圖)

存檔與匯出標頭

  • Ctrl+S/Ctrl+Shift+S:存成 .nxlay(UTF-8、無 BOM)。
  • File > Export to Header (.h)...:呼叫與命令列 --emit-header 相同的產生器,輸出一份 .h(控制項陣列、面板佈局與個數巨集)。 .h 是產物,永遠不要手改。 你的 .c 用 #include 引進它;改了 .nxlay 就要重新匯出, 建置不會替你重新產生,也沒有任何東西檢查兩個檔案有沒有不同步,見第一個 Plugin 4。
匯出標頭的存檔對話框,檔名 hello_ic_panel.h
Export to Header(點圖看完整原圖)

命令列:nxlayout.exe

不開編輯器也能做同樣的檢查,適合自動化與 CI。PDK 的 tools\x64\ 與 tools\x86\ 各有一份, nxlayout.exe 要和同資料夾的 nxlayout_core.dll 放在一起。 檔名 - 代表從標準輸入讀。

rem 驗證並求解,輸出 JSON。預設用 [panel] 的 ref_w / ref_h 當面板大小 nxlayout --solve hello_ic_panel.nxlay rem 指定面板大小,檢查窄面板下有沒有控制項消失 nxlayout --solve hello_ic_panel.nxlay --w 40 --h 10 rem 用字母格顯示求解出的版面(示意,不是真實渲染) nxlayout --ascii hello_ic_panel.nxlay --w 40 --h 10 rem 產生 C 標頭 nxlayout --emit-header hello_ic_panel.nxlay hello_ic_panel.h rem 印出 .nxlay 格式速查卡 nxlayout --format-card
  • --solve 一律把 JSON 印到標準輸出:"ok" 表示驗證有沒有通過,"errors" 是錯誤(含規則名稱與說明), "widgets" 是每個控制項的 visible(1 可見、0 因為裝不下被隱藏)與位置大小。檢查有沒有控制項消失,就看有沒有 "visible":0。
  • 結束碼:0 是成功;驗證失敗是 2。規則是第一個失敗錯誤碼的絕對值,腳本只要判斷是不是 0 就夠了。
  • --solve 沒指定 --w/--h,.nxlay 也沒有 ref_w/ref_h 時,面板尺寸是 0,工具會印警告,這時請補上 --w、--h。
  • 還有一個 --render(輸出 RGB 影像,給截圖之類的自動化用),一般開發用不到。

一個建議的工作流程

  1. 用編輯器(或手寫)設計面板,Error List 清空,存成 xxx_panel.nxlay。
  2. 用 Preview 或 nxlayout --solve --w 40 確認窄面板下重要的控制項還在。
  3. Export to Header 或 nxlayout --emit-header 產生 xxx_panel.h。
  4. 你的 .c #include 它取得控制項編號,在 init 以 LoadLayout 載入 .nxlay 本身(嵌成 RCDATA 資源或放在 DLL 旁邊,見第一個 Plugin 4)。
  5. 之後要改版面:回到步驟 1,存檔後一定重新產生 .h。

除了這裡的 15 種控制項與 11 條規則,.nxlay 格式的完整規格在 PDK 的 docs\NEXUS_LAYOUT_TOOL_SDD.md,nxlayout --format-card 也印得出來。