From fefd526c98c3a14ab2569249575399aa7db26b68 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 12 Oct 2026 19:21:38 +0000 Subject: [PATCH] Select Color: review cleanups - Split ColorEditor::view into mode_row, slider_rows, field_view, hex_row and hex_field; output is unchanged. - hex_string reuses config::rgb_to_hex, and parse_hex documents why it stays separate (it also accepts #RGB). - ink_is_dark uses Color::into_rgba8 instead of rounding by hand. - Remove four translation keys the old dialog used and nothing references any more, from the catalog and all 22 locales. - Eyedropper: without a main window there is no screenshot to wait for, so leave the eyedropper; keep the magnifier inside small windows. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_013rGmDUNr1hUf4zo1X3dak8 --- locales/ar-SA/opencadstudio.ftl | 4 - locales/bg-BG/opencadstudio.ftl | 4 - locales/cs-CZ/opencadstudio.ftl | 4 - locales/de-DE/opencadstudio.ftl | 4 - locales/el-GR/opencadstudio.ftl | 4 - locales/en-US/opencadstudio.ftl | 4 - locales/es-ES/opencadstudio.ftl | 4 - locales/fi-FI/opencadstudio.ftl | 4 - locales/fr-FR/opencadstudio.ftl | 4 - locales/hi-IN/opencadstudio.ftl | 4 - locales/hu-HU/opencadstudio.ftl | 4 - locales/it-IT/opencadstudio.ftl | 4 - locales/ja-JP/opencadstudio.ftl | 4 - locales/ko-KR/opencadstudio.ftl | 4 - locales/lo-LA/opencadstudio.ftl | 4 - locales/nl-NL/opencadstudio.ftl | 4 - locales/pl-PL/opencadstudio.ftl | 4 - locales/pt-BR/opencadstudio.ftl | 4 - locales/ru-RU/opencadstudio.ftl | 4 - locales/tr-TR/opencadstudio.ftl | 4 - locales/zh-CN/opencadstudio.ftl | 4 - locales/zh-TW/opencadstudio.ftl | 4 - src/app/update/mod.rs | 11 +- src/locale_catalog.rs | 4 - src/ui/color_select/editor.rs | 247 ++++++++++++++++-------------- src/ui/color_select/eyedropper.rs | 7 +- src/ui/color_select/math.rs | 7 +- src/ui/color_select/picker.rs | 4 +- 28 files changed, 147 insertions(+), 221 deletions(-) diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index 358066656..35c51636b 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -1334,8 +1334,6 @@ common = .dismiss = إغلاق .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = لا توجد ألوان حديثة بعد - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1343,9 +1341,7 @@ common = .nearest-index-color = أقرب فهرس .exact-index-match = تطابق تام مع الفهرس .cad-color-index-aci-10-249 = فهرس ألوان ACI 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = المستخدمة مؤخرًا .isometric-drafting = الرسم متساوي القياس .f5-cycles-the-active-plane = يبدّل F5 المستوى النشط بالتتابع. .units-5430a1 = { common.units }… diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index 3f7094552..6b313633a 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -1321,8 +1321,6 @@ common = .dismiss = Затваряне .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Все още няма скорошни цветове - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1330,9 +1328,7 @@ common = .nearest-index-color = Най-близък индекс .exact-index-match = Точно съвпадение с индекс .cad-color-index-aci-10-249 = ACI Цветови индекс 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Последно използвани .isometric-drafting = Изометрично чертане .f5-cycles-the-active-plane = F5 превключва последователно активната равнина. .units-5430a1 = { common.units }… diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index cad06d273..43e80d3bf 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -1321,8 +1321,6 @@ common = .dismiss = Zavřít .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Zatím žádné nedávné barvy - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1330,9 +1328,7 @@ common = .nearest-index-color = Nejbližší index .exact-index-match = Přesná shoda s indexem .cad-color-index-aci-10-249 = Barevný index ACI 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Nedávno použité .isometric-drafting = Izometrické kreslení .f5-cycles-the-active-plane = F5 cyklicky přepíná aktivní rovinu. .units-5430a1 = { common.units }… diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index 3c4f4b9d5..350d07c6b 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -1322,8 +1322,6 @@ common = .dismiss = Schließen .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Noch keine zuletzt verwendeten Farben - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1331,9 +1329,7 @@ common = .nearest-index-color = Nächster Index .exact-index-match = Exakter Index-Treffer .cad-color-index-aci-10-249 = ACI Farbindex 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Zuletzt verwendet .isometric-drafting = Isometrisches Zeichnen .f5-cycles-the-active-plane = F5 wechselt die aktive Ebene der Reihe nach. .units-5430a1 = { common.units }… diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index 615a14c6d..4726011ca 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -1323,8 +1323,6 @@ common = .dismiss = Κλείσιμο .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Δεν υπάρχουν ακόμη πρόσφατα χρώματα - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1332,9 +1330,7 @@ common = .nearest-index-color = Πλησιέστερος δείκτης .exact-index-match = Ακριβής αντιστοίχιση δείκτη .cad-color-index-aci-10-249 = Δείκτης χρώματος ACI 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Πρόσφατα χρησιμοποιημένα .isometric-drafting = Ισομετρική σχεδίαση .f5-cycles-the-active-plane = Το F5 εναλλάσσει το ενεργό επίπεδο. .units-5430a1 = { common.units }… diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index c4c86910b..961aaa81c 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -1323,8 +1323,6 @@ common = .dismiss = Dismiss .value-8a8de8 = ? .select-color-8dddf1 = Select Color... - .no-recent-colors-yet = No recent colors yet - .true-color-rgb = True Color RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = Index Color .true-color = True Color .standard-colors = Standard colors @@ -1332,9 +1330,7 @@ common = .nearest-index-color = Nearest index .exact-index-match = Exact index match .cad-color-index-aci-10-249 = CAD Color Index (ACI) 10–249 - .color-family-shade-intensity = Color family → · Shade / intensity ↓ .grayscale-250-255 = Grayscale 250–255 - .recently-used = Recently used .isometric-drafting = Isometric drafting .f5-cycles-the-active-plane = F5 cycles the active plane. .units-5430a1 = Units… diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index c21e510bc..3eeaa2d67 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -1322,8 +1322,6 @@ common = .dismiss = Cerrar .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Aún no hay colores recientes - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1331,9 +1329,7 @@ common = .nearest-index-color = Índice más cercano .exact-index-match = Coincide con un índice .cad-color-index-aci-10-249 = Índice de color ACI 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Usados recientemente .isometric-drafting = Dibujo isométrico .f5-cycles-the-active-plane = F5 alterna el plano activo. .units-5430a1 = { common.units }… diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index c8067d189..3bb153c47 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -1321,8 +1321,6 @@ common = .dismiss = Sulje .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Ei vielä viimeksi käytettyjä värejä - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1330,9 +1328,7 @@ common = .nearest-index-color = Lähin indeksi .exact-index-match = Täsmälleen indeksiväri .cad-color-index-aci-10-249 = ACI väriindeksi 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Viimeksi käytetyt .isometric-drafting = Isometrinen piirtäminen .f5-cycles-the-active-plane = F5 vaihtaa aktiivista tasoa. .units-5430a1 = { common.units }… diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index 014bb5e83..d8379605a 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -1322,8 +1322,6 @@ common = .dismiss = Fermer .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Aucune couleur récente - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1331,9 +1329,7 @@ common = .nearest-index-color = Index le plus proche .exact-index-match = Correspondance exacte d'index .cad-color-index-aci-10-249 = ACI Indice de couleur 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Utilisés récemment .isometric-drafting = Dessin isométrique .f5-cycles-the-active-plane = F5 fait défiler les plans actifs. .units-5430a1 = { common.units }… diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index 8a35dd54e..d1dac675c 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -1310,8 +1310,6 @@ common = .dismiss = बंद करें .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = अभी कोई हालिया रंग नहीं है - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1319,9 +1317,7 @@ common = .nearest-index-color = निकटतम इंडेक्स .exact-index-match = इंडेक्स से सटीक मेल .cad-color-index-aci-10-249 = ACI रंग सूचकांक 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = हाल में उपयोग किए गए .isometric-drafting = सममितीय आरेखन .f5-cycles-the-active-plane = F5 सक्रिय तल को क्रम से बदलता है। .units-5430a1 = { common.units }… diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 4e0c17b55..2d06a13c5 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -1321,8 +1321,6 @@ common = .dismiss = Bezárás .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Még nincsenek legutóbbi színek - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1330,9 +1328,7 @@ common = .nearest-index-color = Legközelebbi index .exact-index-match = Pontos indexegyezés .cad-color-index-aci-10-249 = ACI színindex 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Legutóbb használt .isometric-drafting = Izometrikus rajzolás .f5-cycles-the-active-plane = Az F5 váltja az aktív síkot. .units-5430a1 = { common.units }… diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index f1f5b6d5b..24d7aa5cc 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -1321,8 +1321,6 @@ common = .dismiss = Chiudi .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Nessun colore recente - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1330,9 +1328,7 @@ common = .nearest-index-color = Indice più vicino .exact-index-match = Corrispondenza esatta indice .cad-color-index-aci-10-249 = ACI Indice colori 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Usati di recente .isometric-drafting = Disegno isometrico .f5-cycles-the-active-plane = F5 alterna il piano attivo. .units-5430a1 = { common.units }… diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index c13aead95..92eaa0a80 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -1312,8 +1312,6 @@ common = .dismiss = 閉じる .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = 最近使った色はありません - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1321,9 +1319,7 @@ common = .nearest-index-color = 最も近いインデックス .exact-index-match = インデックスと完全一致 .cad-color-index-aci-10-249 = ACI カラーインデックス 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = 最近使用した色 .isometric-drafting = アイソメ図作成 .f5-cycles-the-active-plane = F5でアクティブな平面を順に切り替えます。 .units-5430a1 = { common.units }… diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 9744e1e36..7078ff4dd 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -1321,8 +1321,6 @@ common = .dismiss = 닫기 .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = 최근 사용한 색상이 없습니다 - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1330,9 +1328,7 @@ common = .nearest-index-color = 가장 가까운 인덱스 .exact-index-match = 인덱스와 정확히 일치 .cad-color-index-aci-10-249 = ACI 컬러 인덱스 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = 최근 사용 .isometric-drafting = 등각 제도 .f5-cycles-the-active-plane = F5 키로 활성 평면을 순환 전환합니다. .units-5430a1 = { common.units }… diff --git a/locales/lo-LA/opencadstudio.ftl b/locales/lo-LA/opencadstudio.ftl index 2082db648..0961364ed 100644 --- a/locales/lo-LA/opencadstudio.ftl +++ b/locales/lo-LA/opencadstudio.ftl @@ -1323,8 +1323,6 @@ common = .dismiss = ປິດອອກ .value-8a8de8 = ? .select-color-8dddf1 = ເລືອກສີ... - .no-recent-colors-yet = ຍັງບໍ່ມີສີຫຼ້າສຸດ - .true-color-rgb = True Color RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = ສີດັດຊະນີ .true-color = True Color .standard-colors = ສີມາດຕະຖານ @@ -1332,9 +1330,7 @@ common = .nearest-index-color = ດັດຊະນີທີ່ໃກ້ທີ່ສຸດ .exact-index-match = ກົງກັບດັດຊະນີພໍດີ .cad-color-index-aci-10-249 = CAD Color Index (ACI) 10–249 - .color-family-shade-intensity = ກຸ່ມສີ → · ລະດັບສີ / ຄວາມເຂັ້ມ ↓ .grayscale-250-255 = ລະດັບສີເທົາ 250–255 - .recently-used = ໃຊ້ຫຼ້າສຸດ .isometric-drafting = ການຂຽນແບບໄອໂຊເມຕຣິກ .f5-cycles-the-active-plane = F5 ປ່ຽນລະນາບທີ່ໃຊ້ງານວຽນໄປ. .units-5430a1 = ຫົວໜ່ວຍ… diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index fdf8b12df..10c209ee6 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -1320,8 +1320,6 @@ common = .dismiss = Sluiten .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Nog geen recente kleuren - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1329,9 +1327,7 @@ common = .nearest-index-color = Dichtstbijzijnde index .exact-index-match = Exacte indexkleur .cad-color-index-aci-10-249 = ACI Kleurindex 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Recent gebruikt .isometric-drafting = Isometrisch tekenen .f5-cycles-the-active-plane = F5 wisselt het actieve vlak. .units-5430a1 = { common.units }… diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index c0ace6edb..df099a5de 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -1321,8 +1321,6 @@ common = .dismiss = Zamknij .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Brak ostatnio używanych kolorów - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1330,9 +1328,7 @@ common = .nearest-index-color = Najbliższy indeks .exact-index-match = Dokładne dopasowanie indeksu .cad-color-index-aci-10-249 = Indeks kolorów ACI 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Ostatnio używane .isometric-drafting = Rysowanie izometryczne .f5-cycles-the-active-plane = F5 przełącza aktywną płaszczyznę. .units-5430a1 = { common.units }… diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index 95c7f9245..047069429 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -1322,8 +1322,6 @@ common = .dismiss = Fechar .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Nenhuma cor recente ainda - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1331,9 +1329,7 @@ common = .nearest-index-color = Índice mais próximo .exact-index-match = Corresponde exatamente ao índice .cad-color-index-aci-10-249 = Índice de cor ACI 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Usados recentemente .isometric-drafting = Desenho isométrico .f5-cycles-the-active-plane = F5 alterna o plano ativo. .units-5430a1 = { common.units }… diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 29224ec62..d9ba65410 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -1325,8 +1325,6 @@ common = .dismiss = Закрыть .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Недавно использованных цветов пока нет - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1334,9 +1332,7 @@ common = .nearest-index-color = Ближайший индекс .exact-index-match = Точное совпадение с индексом .cad-color-index-aci-10-249 = Индекс цвета ACI 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Недавно использованные .isometric-drafting = Изометрическое черчение .f5-cycles-the-active-plane = F5 циклически переключает активную плоскость. .units-5430a1 = { common.units }… diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index a5246382f..6574106d6 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -1308,8 +1308,6 @@ common = .dismiss = Kapat .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = Henüz son kullanılan renk yok - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1317,9 +1315,7 @@ common = .nearest-index-color = En yakın indeks .exact-index-match = Tam indeks eşleşmesi .cad-color-index-aci-10-249 = ACI renk dizini 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = Son kullanılanlar .isometric-drafting = İzometrik çizim .f5-cycles-the-active-plane = F5 etkin düzlemi sırayla değiştirir. .units-5430a1 = { common.units }… diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index 0af74a805..cdc3d8540 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -1309,8 +1309,6 @@ common = .dismiss = 关闭 .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = 尚无最近使用的颜色 - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1318,9 +1316,7 @@ common = .nearest-index-color = 最接近的索引色 .exact-index-match = 与索引色完全匹配 .cad-color-index-aci-10-249 = ACI 颜色索引 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = 最近使用 .isometric-drafting = 等轴测绘图 .f5-cycles-the-active-plane = F5 循环切换活动平面。 .units-5430a1 = { common.units }… diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index 505cb7f59..5b2ea00b0 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -1321,8 +1321,6 @@ common = .dismiss = 關閉 .value-8a8de8 = ? .select-color-8dddf1 = { common.select-color }… - .no-recent-colors-yet = 尚無最近使用的顏色 - .true-color-rgb = { common.true-color } RGB __ocs_fmt_0__, __ocs_fmt_1__, __ocs_fmt_2__ .index-color = { common.color } (ACI) .true-color = { common.color } (RGB) .standard-colors = { common.standard } · { common.color } @@ -1330,9 +1328,7 @@ common = .nearest-index-color = 最接近的索引色 .exact-index-match = 與索引色完全相符 .cad-color-index-aci-10-249 = ACI 顏色索引 10–249 - .color-family-shade-intensity = { common.color-family } → · { common.shade } / { properties.intensity } ↓ .grayscale-250-255 = { common.grayscale } 250–255 - .recently-used = 最近使用 .isometric-drafting = 等角製圖 .f5-cycles-the-active-plane = F5 循環切換作用中平面。 .units-5430a1 = { common.units }… diff --git a/src/app/update/mod.rs b/src/app/update/mod.rs index 6b25dd7e1..8eece9b24 100644 --- a/src/app/update/mod.rs +++ b/src/app/update/mod.rs @@ -11039,13 +11039,16 @@ impl OpenCADStudio { } Some(crate::ui::color_select::Outcome::Screenshot) => { use crate::ui::color_select::{eyedropper::EyedropperMsg, ColorPickerMsg}; - self.main_window.map_or_else(Task::none, |id| { - iced::window::screenshot(id).map(|shot| { + match self.main_window { + Some(id) => iced::window::screenshot(id).map(|shot| { Message::ColorPicker(ColorPickerMsg::Eyedropper( EyedropperMsg::Shot(shot), )) - }) - }) + }), + // Nothing to capture: leave the eyedropper instead + // of waiting for a screenshot that never comes. + None => self.update(Message::ColorPicker(ColorPickerMsg::Cancel)), + } } None => Task::none(), } diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index 2a01c1f43..6c943a16a 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -4689,8 +4689,6 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "Dismiss" => Some(("common", "dismiss")), "?" => Some(("common", "value-8a8de8")), "Select Color..." => Some(("common", "select-color-8dddf1")), - "No recent colors yet" => Some(("common", "no-recent-colors-yet")), - "True Color RGB {r}, {g}, {b}" => Some(("common", "true-color-rgb")), "Index Color" => Some(("common", "index-color")), "True Color" => Some(("common", "true-color")), "Standard colors" => Some(("common", "standard-colors")), @@ -4698,9 +4696,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "Nearest index" => Some(("common", "nearest-index-color")), "Exact index match" => Some(("common", "exact-index-match")), "CAD Color Index (ACI) 10–249" => Some(("common", "cad-color-index-aci-10-249")), - "Color family → · Shade / intensity ↓" => Some(("common", "color-family-shade-intensity")), "Grayscale 250–255" => Some(("common", "grayscale-250-255")), - "Recently used" => Some(("common", "recently-used")), "Isometric drafting" => Some(("common", "isometric-drafting")), "F5 cycles the active plane." => Some(("common", "f5-cycles-the-active-plane")), "Units…" => Some(("common", "units-5430a1")), diff --git a/src/ui/color_select/editor.rs b/src/ui/color_select/editor.rs index f003629c4..ea97384c7 100644 --- a/src/ui/color_select/editor.rs +++ b/src/ui/color_select/editor.rs @@ -138,14 +138,25 @@ impl ColorEditor { /// `mode_end` sits at the far right of the mode buttons (the pipette); /// `hex_end` at the far right of the hex row (the nearest index colour). + /// The field view shows the hex value beside H, S and B and leaves out + /// `hex_end`; the slider views end on a hex row. pub fn view<'a>( &'a self, mode_end: Option>, hex_end: Option>, ) -> Element<'a, Message> { - let Hsb { h, s, b } = self.hsb; - let (r, g, bl) = self.rgb; + let view = column![self.mode_row(mode_end)].spacing(12); + match self.mode { + EditorMode::Hsb | EditorMode::Rgb => view + .push(self.slider_rows()) + .push(self.hex_row(hex_end)) + .into(), + EditorMode::Field => view.push(self.field_view()).into(), + } + } + /// HSB, RGB and the gradient-field button, with `end` at the far right. + fn mode_row<'a>(&self, end: Option>) -> Element<'a, Message> { let mode_button = |content: Element<'a, Message>, mode: EditorMode| { let active = self.mode == mode; button(container(content).center(Length::Fill)) @@ -189,32 +200,50 @@ impl ColorEditor { Space::new().width(Length::Fill), ] .spacing(6); - if let Some(end) = mode_end { + if let Some(end) = end { modes = modes.push(end); } + modes.into() + } - let hex = self - .hex_draft - .clone() - .unwrap_or_else(|| math::hex_string(r, g, bl)); - let hex_field = move || { - row![ - text(t!("Hex")).size(11).style(super::picker::muted_text), - text_input("", &hex) - .on_input(|value| msg(EditorMsg::HexInput(value))) - .on_submit(msg(EditorMsg::HexSubmit)) - .size(12) - .font(iced::Font::MONOSPACE) - .padding([5, 6]) - .width(Length::Fixed(74.0)), + /// Three gradient sliders: hue, saturation and brightness, or red, green + /// and blue. + fn slider_rows<'a>(&self) -> Element<'a, Message> { + let Hsb { h, s, b } = self.hsb; + let (r, g, bl) = self.rgb; + let rows = if self.mode == EditorMode::Rgb { + let ends = |lo: (u8, u8, u8), hi: (u8, u8, u8)| { + vec![(0.0, rgb_color(lo)), (1.0, rgb_color(hi))] + }; + let byte = |f: fn(u8) -> EditorMsg| move |v: f32| f(v.round() as u8); + column![ + channel( + "R", + f32::from(r), + 255.0, + None, + ends((0, g, bl), (255, g, bl)), + byte(EditorMsg::Red) + ), + channel( + "G", + f32::from(g), + 255.0, + None, + ends((r, 0, bl), (r, 255, bl)), + byte(EditorMsg::Green) + ), + channel( + "B", + f32::from(bl), + 255.0, + None, + ends((r, g, 0), (r, g, 255)), + byte(EditorMsg::Blue) + ), ] - .spacing(8) - .align_y(iced::Center) - }; - let field_mode = self.mode == EditorMode::Field; - - let editor: Element<'a, Message> = match self.mode { - EditorMode::Hsb => column![ + } else { + column![ channel("H", h, 360.0, Some('°'), hue_stops(), EditorMsg::Hue), channel( "S", @@ -233,103 +262,85 @@ impl ColorEditor { EditorMsg::Brightness, ), ] - .spacing(ROW_GAP) - .into(), - EditorMode::Rgb => { - let ends = |lo: (u8, u8, u8), hi: (u8, u8, u8)| { - vec![(0.0, rgb_color(lo)), (1.0, rgb_color(hi))] - }; - let byte = |f: fn(u8) -> EditorMsg| move |v: f32| f(v.round() as u8); - column![ - channel( - "R", - f32::from(r), - 255.0, - None, - ends((0, g, bl), (255, g, bl)), - byte(EditorMsg::Red) - ), - channel( - "G", - f32::from(g), - 255.0, - None, - ends((r, 0, bl), (r, 255, bl)), - byte(EditorMsg::Green) - ), - channel( - "B", - f32::from(bl), - 255.0, - None, - ends((r, g, 0), (r, g, 255)), - byte(EditorMsg::Blue) - ), - ] - .spacing(ROW_GAP) - .into() - } - EditorMode::Field => { - let area = - ColorArea::new(hsb_color(h, 1.0, 1.0), rgb_color(self.rgb), s, b, |s, b| { - msg(EditorMsg::Field(s, b)) - }) - .height(Length::Fixed(FIELD_HEIGHT)); - // A vertical slider grows upwards; the strip runs red at the top. - let strip = stack![ - container(Space::new()) - .width(STRIP_WIDTH) - .height(FIELD_HEIGHT) - .style(|_theme: &Theme| gradient_box(std::f32::consts::PI, &hue_stops())), - vertical_slider(0.0..=360.0, 360.0 - h, |v| msg(EditorMsg::Hue(360.0 - v))) - .width(STRIP_WIDTH) - .height(FIELD_HEIGHT) - .style(handle_style), - ]; - let value = |letter: &'static str, - v: f32, - max: f32, - unit: char, - f: fn(f32) -> EditorMsg| { - row![ - text(letter).size(12).font(iced::Font::MONOSPACE), - number_box(v, max, Some(unit), f), - ] - .spacing(4) - .align_y(iced::Center) - }; - column![ - row![area, strip].spacing(12), - // H, S and B on the left, the hex value on the right. - row![ - value("H", h, 360.0, '°', EditorMsg::Hue), - value("S", s * 100.0, 100.0, '%', EditorMsg::Saturation), - value("B", b * 100.0, 100.0, '%', EditorMsg::Brightness), - Space::new().width(Length::Fill), - hex_field(), - ] - .spacing(10) - .align_y(iced::Center), - ] - // 108 + 10 matches the slider views' 3 × 26 + 2 × 14 + 12. - .spacing(10) - .into() - } }; + rows.spacing(ROW_GAP).into() + } - // The field view shows the hex value beside H, S and B and leaves out - // the nearest index colour; the slider views end on a hex row. - let mut view = column![modes, editor].spacing(12); - if !field_mode { - let mut hex_row = row![hex_field(), Space::new().width(Length::Fill)] - .spacing(8) - .align_y(iced::Center); - if let Some(end) = hex_end { - hex_row = hex_row.push(end); - } - view = view.push(hex_row); + /// The saturation/brightness field with its hue strip, and below it H, S + /// and B on the left and the hex value on the right. + fn field_view<'a>(&self) -> Element<'a, Message> { + let Hsb { h, s, b } = self.hsb; + let area = ColorArea::new(hsb_color(h, 1.0, 1.0), rgb_color(self.rgb), s, b, |s, b| { + msg(EditorMsg::Field(s, b)) + }) + .height(Length::Fixed(FIELD_HEIGHT)); + // A vertical slider grows upwards; the strip runs red at the top. + let strip = stack![ + container(Space::new()) + .width(STRIP_WIDTH) + .height(FIELD_HEIGHT) + .style(|_theme: &Theme| gradient_box(std::f32::consts::PI, &hue_stops())), + vertical_slider(0.0..=360.0, 360.0 - h, |v| msg(EditorMsg::Hue(360.0 - v))) + .width(STRIP_WIDTH) + .height(FIELD_HEIGHT) + .style(handle_style), + ]; + let value = + |letter: &'static str, v: f32, max: f32, unit: char, f: fn(f32) -> EditorMsg| { + row![ + text(letter).size(12).font(iced::Font::MONOSPACE), + number_box(v, max, Some(unit), f), + ] + .spacing(4) + .align_y(iced::Center) + }; + column![ + row![area, strip].spacing(12), + row![ + value("H", h, 360.0, '°', EditorMsg::Hue), + value("S", s * 100.0, 100.0, '%', EditorMsg::Saturation), + value("B", b * 100.0, 100.0, '%', EditorMsg::Brightness), + Space::new().width(Length::Fill), + self.hex_field(), + ] + .spacing(10) + .align_y(iced::Center), + ] + // 108 + 10 matches the slider views' 3 × 26 + 2 × 14 + 12. + .spacing(10) + .into() + } + + /// The hex value with `end` (the nearest index colour) at the far right. + fn hex_row<'a>(&self, end: Option>) -> Element<'a, Message> { + let mut hex_row = row![self.hex_field(), Space::new().width(Length::Fill)] + .spacing(8) + .align_y(iced::Center); + if let Some(end) = end { + hex_row = hex_row.push(end); } - view.into() + hex_row.into() + } + + fn hex_field<'a>(&self) -> Element<'a, Message> { + let (r, g, b) = self.rgb; + let hex = self + .hex_draft + .clone() + .unwrap_or_else(|| math::hex_string(r, g, b)); + row![ + text(t!("Hex")).size(11).style(super::picker::muted_text), + text_input("", &hex) + .on_input(|value| msg(EditorMsg::HexInput(value))) + .on_submit(msg(EditorMsg::HexSubmit)) + .size(12) + .font(iced::Font::MONOSPACE) + .padding([5, 6]) + .width(Length::Fixed(74.0)), + ] + .spacing(8) + .align_y(iced::Center) + .into() } } diff --git a/src/ui/color_select/eyedropper.rs b/src/ui/color_select/eyedropper.rs index 2c7050e38..2d24822b9 100644 --- a/src/ui/color_select/eyedropper.rs +++ b/src/ui/color_select/eyedropper.rs @@ -119,16 +119,19 @@ impl Eyedropper { let size = GRID as f32 * CELL + 8.0; let window_w = shot.size.width as f32 / shot.scale_factor; let window_h = shot.size.height as f32 / shot.scale_factor; + // In a very small window neither side fits; stay inside the top-left. let x = if cursor.x + OFFSET + size > window_w { cursor.x - OFFSET - size } else { cursor.x + OFFSET - }; + } + .max(0.0); let y = if cursor.y + OFFSET + size + 20.0 > window_h { cursor.y - OFFSET - size - 20.0 } else { cursor.y + OFFSET - }; + } + .max(0.0); stack![catcher, pin(loupe).x(x).y(y)].into() } } diff --git a/src/ui/color_select/math.rs b/src/ui/color_select/math.rs index 8e4aa7e5d..74ab9968d 100644 --- a/src/ui/color_select/math.rs +++ b/src/ui/color_select/math.rs @@ -78,12 +78,13 @@ pub fn nearest_aci(r: u8, g: u8, b: u8) -> u8 { codec::types::aci_table::nearest_aci(r, g, b) } -/// `#RRGGBB`, upper case. +/// `#RRGGBB`, upper case — the same format the Options hex fields store. pub fn hex_string(r: u8, g: u8, b: u8) -> String { - format!("#{r:02X}{g:02X}{b:02X}") + crate::app::config::rgb_to_hex([r, g, b]) } -/// Parse `#RRGGBB`, `RRGGBB`, `#RGB` or `RGB`. +/// Parse `#RRGGBB`, `RRGGBB`, `#RGB` or `RGB`. Unlike `config::parse_hex`, +/// which Options uses, this also accepts the short three-digit form. pub fn parse_hex(text: &str) -> Option<(u8, u8, u8)> { let digits = text.trim().trim_start_matches('#'); if !digits.chars().all(|c| c.is_ascii_hexdigit()) { diff --git a/src/ui/color_select/picker.rs b/src/ui/color_select/picker.rs index c1116f53a..ccd63b85d 100644 --- a/src/ui/color_select/picker.rs +++ b/src/ui/color_select/picker.rs @@ -510,8 +510,8 @@ fn picker_msg(msg: ColorPickerMsg) -> Message { } fn ink_is_dark(color: Color) -> bool { - let byte = |c: f32| (c * 255.0).round() as u8; - math::ink_is_dark(byte(color.r), byte(color.g), byte(color.b)) + let [r, g, b, _] = color.into_rgba8(); + math::ink_is_dark(r, g, b) } fn filled(color: Color) -> container::Style {