From 1c8e3ff3d7f8374865923b500833a7b481d65044 Mon Sep 17 00:00:00 2001 From: Karim Jerbi Date: Mon, 14 Sep 2026 20:51:48 +0100 Subject: [PATCH] feat(xref): 8-item filtered row menu, preview on selection, details display size Row right-click menu is exactly Open, Attach..., Unload, Reload, Detach, Change Path Type group with Make Absolute, Make Relative, Remove Path, Select New Path, Find and Replace. Change Path Type renders as indented group. Open uses OCS for DWG and OS default for images and PDFs. Preview decodes on selection change, not only at refresh. Details shows placed display width and height for image instances. --- locales/ar-SA/opencadstudio.ftl | 5 ++ locales/bg-BG/opencadstudio.ftl | 5 ++ locales/cs-CZ/opencadstudio.ftl | 5 ++ locales/de-DE/opencadstudio.ftl | 5 ++ locales/el-GR/opencadstudio.ftl | 5 ++ locales/en-US/opencadstudio.ftl | 5 ++ locales/es-ES/opencadstudio.ftl | 5 ++ locales/fi-FI/opencadstudio.ftl | 5 ++ locales/fr-FR/opencadstudio.ftl | 5 ++ locales/hi-IN/opencadstudio.ftl | 5 ++ locales/hu-HU/opencadstudio.ftl | 5 ++ locales/it-IT/opencadstudio.ftl | 5 ++ locales/ja-JP/opencadstudio.ftl | 5 ++ locales/ko-KR/opencadstudio.ftl | 5 ++ locales/nl-NL/opencadstudio.ftl | 5 ++ locales/pl-PL/opencadstudio.ftl | 5 ++ locales/pt-BR/opencadstudio.ftl | 5 ++ locales/ru-RU/opencadstudio.ftl | 5 ++ locales/tr-TR/opencadstudio.ftl | 5 ++ locales/zh-CN/opencadstudio.ftl | 5 ++ locales/zh-TW/opencadstudio.ftl | 5 ++ src/app/update/dialog.rs | 4 + src/app/update/mod.rs | 27 ++++++ src/locale_catalog.rs | 5 ++ src/ui/window/xref_manager.rs | 140 ++++++++++++++++++++++++++------ 25 files changed, 256 insertions(+), 25 deletions(-) diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index 373a2dc9a..6ef3a8178 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -3219,6 +3219,11 @@ insert = .xref-old-path-prefix = بادئة المسار القديم .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF احفظ الرسم أولًا لحل مسارات المراجع الخارجية النسبية. .object-s-copied-to-clipboard-base-3-3 = نُسخ __ocs_fmt_0__ كائن إلى الحافظة (الأساس __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = نُسخ __ocs_fmt_0__ كائن إلى الحافظة. diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index 374def6ef..979172ede 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -3206,6 +3206,11 @@ insert = .xref-old-path-prefix = стар префикс на път .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Първо запази чертежа, за да се разрешат относителните XREF пътища. .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ обект(а) копирани в клипборда (база __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = __ocs_fmt_0__ обект(а) копирани в клипборда. diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index f3a1f3d95..686098d6b 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -3204,6 +3204,11 @@ insert = .xref-old-path-prefix = stará předpona cesty .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Nejprve uložte výkres, abyste vyřešili relativní cesty XREF. .object-s-copied-to-clipboard-base-3-3 = Objekt(y) __ocs_fmt_0__ zkopírován do schránky (základna __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = Objekt(y) __ocs_fmt_0__ zkopírován do schránky. diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index 66d8fd7d2..e4acc53ba 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -3205,6 +3205,11 @@ insert = .xref-old-path-prefix = alte Pfadpräfix .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Speichern Sie zuerst die Zeichnung, um relative XREF Pfade aufzulösen. .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ Objekt(e) kopiert ins Zwischenablage (Basis __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = __ocs_fmt_0__ Objekt(e) kopiert ins Clipboard. diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index 4ec38ec7e..871460012 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -3217,6 +3217,11 @@ insert = .xref-old-path-prefix = old path prefix .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ αντικείμενο(α) αντιγράφηκαν στο πρόχειρο (βάση __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = __ocs_fmt_0__ αντικείμενο(α) αντιγράφηκαν στο πρόχειρο. .object-s-cut-to-clipboard = __ocs_fmt_0__ αντικείμενο(α) αποκόπηκαν στο πρόχειρο. diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index c34f880aa..2299a86ce 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -3218,6 +3218,11 @@ insert = .xref-old-path-prefix = old path prefix .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ object(s) copied to clipboard (base __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = __ocs_fmt_0__ object(s) copied to clipboard. .object-s-cut-to-clipboard = __ocs_fmt_0__ object(s) cut to clipboard. diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index cc858fc38..9b1a12e95 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -3207,6 +3207,11 @@ insert = .xref-old-path-prefix = prefijo de ruta antiguo .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Guarde primero el dibujo para resolver las rutas relativas de referencias externas. .object-s-copied-to-clipboard-base-3-3 = Se copiaron __ocs_fmt_0__ objetos al portapapeles (base __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = Se copiaron __ocs_fmt_0__ objetos al portapapeles. diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index c6bae9edd..2bfccfa85 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -3206,6 +3206,11 @@ insert = .xref-old-path-prefix = vanha polun etuliite .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Tallenna piirustus ensin määrittääksesi suhteelliset XREF-polut. .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ objekti(t) kopioitu leikepöydälle (perus __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = __ocs_fmt_0__ objekti(t) kopioitu leikepöydälle. diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index 57d8f48bd..b9bee5d0b 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -3207,6 +3207,11 @@ insert = .xref-old-path-prefix = ancien préfixe de chemin .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Enregistrez d’abord le dessin afin de résoudre les chemins XREF relatifs. .object-s-copied-to-clipboard-base-3-3 = Objets copiés dans le presse-papiers : __ocs_fmt_0__ (point de base __ocs_fmt_1__, __ocs_fmt_2__). .object-s-copied-to-clipboard = Objets copiés dans le presse-papiers : __ocs_fmt_0__. diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index ead31defb..dba82326a 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -3195,6 +3195,11 @@ insert = .xref-old-path-prefix = पुराना पथ उपसर्ग .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF सापेक्ष पथ निर्धारित करने के लिए पहले ड्रॉइंग सहेजें। .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ ऑब्जेक्ट (s) क्लिपबोर्ड (बेस __ocs_fmt_1__, __ocs_fmt_2__) को कॉपी किया गया। .object-s-copied-to-clipboard = __ocs_fmt_0__ ऑब्जेक्ट (s) क्लिपबोर्ड पर कॉपी किया गया। diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index faaee7c01..4132bbdce 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -3206,6 +3206,11 @@ insert = .xref-old-path-prefix = régi útvonal-előtag .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Először mentse a rajzot a relatív XREF útvonalak feloldásához. .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ objektum(ok) a vágólapra másolva (alap __ocs_fmt_1__, __ocs_fmt_2__). .object-s-copied-to-clipboard = __ocs_fmt_0__ objektum(ok) a vágólapra másolva. diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index c6bb58edf..1046015fc 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -3206,6 +3206,11 @@ insert = .xref-old-path-prefix = vecchio prefisso percorso .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Salvare prima il disegno per risolvere i percorsi XREF relativi. .object-s-copied-to-clipboard-base-3-3 = Oggetto/i __ocs_fmt_0__ copiati negli appunti (base __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = __ocs_fmt_0__ oggetto/i copiati negli appunti. diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index f0386a21c..7da7c7b01 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -3195,6 +3195,11 @@ insert = .xref-old-path-prefix = 古いパスプレフィックス .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF 相対 XREF パスを解決するには、先に図面を保存してください。 .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ 個のオブジェクトをクリップボードにコピーしました(基点 __ocs_fmt_1__,__ocs_fmt_2__)。 .object-s-copied-to-clipboard = __ocs_fmt_0__ 個のオブジェクトをクリップボードにコピーしました。 diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index c6e31fcf2..180485621 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -3206,6 +3206,11 @@ insert = .xref-old-path-prefix = 이전 경로 접두어 .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF 상대 XREF 경로를 확인하려면 먼저 도면을 저장하십시오. .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ 개체가 클립보드에 복사되었습니다(기본 __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = __ocs_fmt_0__ 개체가 클립보드에 복사되었습니다. diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index d832c891c..d082594de 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -3205,6 +3205,11 @@ insert = .xref-old-path-prefix = oud padprefix .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Sla de tekening eerst op om relatieve XREF paden op te lossen. .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ object(en) naar het klembord gekopieerd (basispunt __ocs_fmt_1__, __ocs_fmt_2__). .object-s-copied-to-clipboard = __ocs_fmt_0__ object(en) naar het klembord gekopieerd. diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index da9cd13fd..04d3e0438 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -3206,6 +3206,11 @@ insert = .xref-old-path-prefix = stary prefiks ścieżki .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Zapisz najpierw rysunek, aby ustalić względne ścieżki XREF. .object-s-copied-to-clipboard-base-3-3 = Obiekt(y) __ocs_fmt_0__ skopiowano do schowka (bazowe __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = Obiekt(y) __ocs_fmt_0__ skopiowano do schowka. diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index b8ba82d1d..d852b816a 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -3208,6 +3208,11 @@ insert = .xref-old-path-prefix = prefixo de caminho antigo .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Salve primeiro o desenho para resolver os caminhos relativos das referências externas. .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ objetos copiados para a área de transferência (base __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = __ocs_fmt_0__ objetos copiados para a área de transferência. diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 89e787366..5f8deda4f 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -3208,6 +3208,11 @@ insert = .xref-old-path-prefix = старый префикс пути .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Сначала сохраните чертёж, чтобы определить относительные пути внешних ссылок. .object-s-copied-to-clipboard-base-3-3 = В буфер обмена скопировано объектов: __ocs_fmt_0__ (базовая точка: __ocs_fmt_1__, __ocs_fmt_2__). .object-s-copied-to-clipboard = В буфер обмена скопировано объектов: __ocs_fmt_0__. diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index b79f3ec26..919571b62 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -3174,6 +3174,11 @@ insert = .xref-old-path-prefix = eski yol öneki .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF Göreli XREF yollarını çözümlemek için önce çizimi kaydedin. .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ nesne panoya kopyalandı (taban __ocs_fmt_1__,__ocs_fmt_2__). .object-s-copied-to-clipboard = __ocs_fmt_0__ nesne panoya kopyalandı. diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index edc701612..76a6cb5d1 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -3190,6 +3190,11 @@ insert = .xref-old-path-prefix = 旧路径前缀 .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF 先保存绘图以解析相亲的XREF路径 。 .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ 对象已复制到剪贴板( 基准 __ocs_fmt_1__,__ocs_fmt_2__) 。 .object-s-copied-to-clipboard = __ocs_fmt_0__ 对象被复制到剪贴板。 diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index 75d39427d..d45295437 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -3202,6 +3202,11 @@ insert = .xref-old-path-prefix = 舊路徑前綴 .xref-attach-dwg = Attach DWG .xref-attach-image = Attach Image + .xref-attach-menu = Attach... + .xref-change-path-type = Change Path Type + .xref-find-and-replace-menu = Find and Replace... + .xref-display-width = Display Width + .xref-display-height = Display Height .xref-save-the-drawing-first-to-resolve-relativ = XREF 先儲存繪圖以解析相親的XREF路徑 。 .object-s-copied-to-clipboard-base-3-3 = __ocs_fmt_0__ 物件已複製到剪貼簿( 基準 __ocs_fmt_1__,__ocs_fmt_2__) 。 .object-s-copied-to-clipboard = __ocs_fmt_0__ 物件被複製到剪貼簿。 diff --git a/src/app/update/dialog.rs b/src/app/update/dialog.rs index 16a053bea..02d062585 100644 --- a/src/app/update/dialog.rs +++ b/src/app/update/dialog.rs @@ -924,6 +924,7 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven return; } let label = match op { + XrefPaletteOp::Open => "XREF-OPEN", XrefPaletteOp::Detach => "XREF-DETACH", XrefPaletteOp::Unload => "XREF-UNLOAD", XrefPaletteOp::Reload => "XREF-RELOAD", @@ -1190,6 +1191,9 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven } } } + XrefPaletteOp::Open | XrefPaletteOp::Attach => { + // Handled in update/mod.rs XrefRowOp dispatch (navigation / picker), not here. + } } if done > 0 { self.post_ref_op(i); diff --git a/src/app/update/mod.rs b/src/app/update/mod.rs index b2d8ca915..ee63513d7 100644 --- a/src/app/update/mod.rs +++ b/src/app/update/mod.rs @@ -2304,6 +2304,33 @@ impl OpenCADStudio { Task::none() } Message::XrefRowOp(index, op) => { + // Open is not a palette op — it navigates to the file. + if op == crate::ui::window::xref_manager::XrefPaletteOp::Open { + self.xref_manager.right_click_select(index); + if let Some(entry) = self.xref_manager.entries.get(index) { + if let Some(found) = entry.found_at.clone() { + let is_dwg = found.to_ascii_lowercase().ends_with(".dwg") + || found.to_ascii_lowercase().ends_with(".dxf"); + if is_dwg { + return Task::done(Message::OpenRecent(std::path::PathBuf::from(found))); + } else { + let _ = open::that_detached(&found); + } + } else { + self.command_line.push_error( + crate::t!("File not found — check the saved path.").as_ref(), + ); + } + } + return Task::none(); + } + // For XrefPathPick the row menu just sets the anchor; the + // picker's result handler does the work. Don't run it through + // xref_manager_op. + if matches!(op, crate::ui::window::xref_manager::XrefPaletteOp::Attach) { + self.xref_manager.right_click_select(index); + return Task::done(Message::XAttachPick); + } // Row-scoped op: select the row first, then run the op. self.xref_manager.right_click_select(index); self.xref_manager_op(op); diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index 48ed487b9..72ced7adc 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -3160,6 +3160,11 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "File References" => Some(("insert", "xref-file-references")), "Attach DWG" => Some(("insert", "xref-attach-dwg")), "Attach Image" => Some(("insert", "xref-attach-image")), + "Attach..." => Some(("insert", "xref-attach-menu")), + "Change Path Type" => Some(("insert", "xref-change-path-type")), + "Find and Replace..." => Some(("insert", "xref-find-and-replace-menu")), + "Display Width" => Some(("insert", "xref-display-width")), + "Display Height" => Some(("insert", "xref-display-height")), "Change Path" => Some(("insert", "xref-change-path")), "Make Absolute" => Some(("insert", "xref-make-absolute")), "Make Relative" => Some(("insert", "xref-make-relative")), diff --git a/src/ui/window/xref_manager.rs b/src/ui/window/xref_manager.rs index 231ec70eb..471f7337e 100644 --- a/src/ui/window/xref_manager.rs +++ b/src/ui/window/xref_manager.rs @@ -180,6 +180,7 @@ pub enum SelectExtend { /// Selection-gated palette operation the toolbar offers. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum XrefPaletteOp { + Open, Detach, Unload, Reload, @@ -291,23 +292,10 @@ impl XrefManagerPanel { .iter() .position(|e| e.key == k && e.saved_path == p) }); - // Previews decode here (not in `view`, which must stay pure): the - // anchor entry only, and only under single selection — the spec shows - // a preview solely for one selected reference. + // Previews decode here and on selection change (view stays pure): + // the anchor entry only, and only under single selection. self.previews.clear(); - if self.selected.len() <= 1 { - if let Some(a) = self.anchor.and_then(|i| self.entries.get(i)) { - if let (Some(found), Some(img)) = - (a.found_at.clone(), reference_preview(a)) - { - let (w, h) = (img.width(), img.height()); - self.previews.insert( - (a.key, found), - iced::widget::image::Handle::from_rgba(w, h, img.into_raw()), - ); - } - } - } + self.ensure_preview_for_anchor(); self.expanded.retain(|k| live_keys.contains(k)); self.entries .iter() @@ -334,6 +322,7 @@ impl XrefManagerPanel { self.selected.clear(); self.selected.insert(index); self.anchor = Some(index); + self.ensure_preview_for_anchor(); return; } match extend { @@ -364,6 +353,7 @@ impl XrefManagerPanel { } } } + self.ensure_preview_for_anchor(); } /// Legacy toggle entry point: Ctrl-style toggle in list mode, single @@ -382,6 +372,8 @@ impl XrefManagerPanel { } if !self.selected.contains(&index) { self.click_select(index, SelectExtend::Single); + } else { + self.ensure_preview_for_anchor(); } } @@ -390,6 +382,27 @@ impl XrefManagerPanel { self.tree = !self.tree; } + fn ensure_preview_for_anchor(&mut self) { + if self.selected.len() > 1 { + return; + } + let Some(a) = self.anchor.and_then(|i| self.entries.get(i)) else { + return; + }; + let Some(found) = a.found_at.clone() else { + return; + }; + let key = (a.key, found.clone()); + if self.previews.contains_key(&key) { + return; + } + if let Some(img) = reference_preview(a) { + let (w, h) = (img.width(), img.height()); + self.previews + .insert(key, iced::widget::image::Handle::from_rgba(w, h, img.into_raw())); + } + } + /// Total table content width: column widths plus inter-column gutters. /// Header, rows, and grab zones all share this geometry so columns align. pub fn table_content_width(&self) -> f32 { @@ -1472,23 +1485,75 @@ fn menu_row(label: String, msg: Message) -> Element<'static, Message> { .into() } -/// Per-row right-click menu. Each item targets its own row, so the -/// operation applies to the row under the cursor. Nested rows report -/// per-entry errors from the engine, matching the CLI wording. +fn menu_header(label: String) -> Element<'static, Message> { + container(text(label).size(11).style(|theme: &Theme| iced::widget::text::Style { + color: Some(theme.palette().background.base.text.scale_alpha(0.55)), + })) + .padding([6, 12]) + .width(Fill) + .into() +} + +fn menu_separator() -> Element<'static, Message> { + container(iced::widget::Space::new().height(Length::Fixed(1.0))) + .style(|theme: &Theme| container::Style { + background: Some(Background::Color(theme.palette().background.neutral.color)), + ..Default::default() + }) + .padding([0, 8]) + .width(Fill) + .into() +} + +/// Per-row right-click menu. Eight items exactly: universal tools + +/// path tools. No Bind, no Attach/Overlay — those are DWG-only and +/// hidden entirely. Change Path Type renders as an indented group +/// because iced_aw ContextMenu has no nested flyout. fn row_menu_for(index: usize) -> Element<'static, Message> { let item = |label: &str, op: XrefPaletteOp| -> Element<'static, Message> { menu_row(label.to_string(), Message::XrefRowOp(index, op)) }; + let pathtype_item = |label: &str, pt: Pathtype| -> Element<'static, Message> { + container(menu_row( + label.to_string(), + Message::XrefRowOp(index, XrefPaletteOp::Pathtype(pt)), + )) + .padding(Padding { + left: 12.0, + ..Padding::default() + }) + .width(Fill) + .into() + }; container( column![ - item(&crate::t!("Detach").into_owned(), XrefPaletteOp::Detach), + item(&crate::t!("Open").into_owned(), XrefPaletteOp::Open), + item(&crate::t!("Attach...").into_owned(), XrefPaletteOp::Attach), item(&crate::t!("Unload").into_owned(), XrefPaletteOp::Unload), item(&crate::t!("Reload").into_owned(), XrefPaletteOp::Reload), - item(&crate::t!("Bind").into_owned(), XrefPaletteOp::Bind), - item(&crate::t!("Overlay").into_owned(), XrefPaletteOp::Overlay), - item(&crate::t!("Attach DWG").into_owned(), XrefPaletteOp::Attach), + item(&crate::t!("Detach").into_owned(), XrefPaletteOp::Detach), + menu_separator(), + menu_header(crate::t!("Change Path Type").into_owned()), + pathtype_item( + &crate::t!("Make Absolute").into_owned(), + Pathtype::Full + ), + pathtype_item( + &crate::t!("Make Relative").into_owned(), + Pathtype::Relative + ), + pathtype_item(&crate::t!("Remove Path").into_owned(), Pathtype::None), + menu_separator(), + menu_row( + crate::t!("Select New Path").into_owned(), + Message::XrefPathPick + ), + menu_row( + crate::t!("Find and Replace...").into_owned(), + Message::XrefFindReplacePrompt + ), ] - .spacing(2) + .spacing(1) .padding(4), ) .style(|theme: &Theme| container::Style { @@ -1502,7 +1567,7 @@ fn row_menu_for(index: usize) -> Element<'static, Message> { }, ..Default::default() }) - .width(Length::Fixed(200.0)) + .width(Length::Fixed(220.0)) .into() } @@ -1791,6 +1856,17 @@ fn details_pane<'a>(entry: Option<&'a ReferenceEntry>, doc: &'a CadDocument) -> format!("{:?}", def.resolution_unit), )); } + if let Some((w, h)) = find_image_display_size(doc, e.key) { + rows = rows + .push(detail_row( + crate::t!("Display Width"), + format!("{:.2}", w), + )) + .push(detail_row( + crate::t!("Display Height"), + format!("{:.2}", h), + )); + } } rows.into() } @@ -1865,6 +1941,20 @@ fn find_image_def( }) } +fn find_image_display_size(doc: &CadDocument, key: u64) -> Option<(f64, f64)> { + let handle = acadrust::types::Handle::from(key); + for entity in doc.entities() { + if let acadrust::EntityType::RasterImage(img) = entity { + if img.definition_handle == Some(handle) { + let w = (img.u_vector.x.powi(2) + img.u_vector.y.powi(2) + img.u_vector.z.powi(2)).sqrt(); + let h = (img.v_vector.x.powi(2) + img.v_vector.y.powi(2) + img.v_vector.z.powi(2)).sqrt(); + return Some((w, h)); + } + } + } + None +} + fn detail_row<'a>( label: impl Into>, value: impl Into>,