diff --git a/crates/ui-egui/src/app.rs b/crates/ui-egui/src/app.rs index 910dd8e49..9bbc26d4f 100644 --- a/crates/ui-egui/src/app.rs +++ b/crates/ui-egui/src/app.rs @@ -561,7 +561,8 @@ impl VectorcraftApp { tools_float::clear_canvas_dock_zone(&ctx); } // Beside the canvas, docked Tools draws inside the canvas panel (`toolbar::show_beside_canvas`). - if self.ui.toolbar && self.ui.screen_mode < 3 && (!self.ui.tools_beside_canvas || self.ui.toolbar_pos.is_some()) { + // So does Tools docked on the right, left of the panels. + if self.ui.toolbar && self.ui.screen_mode < 3 && ((!self.ui.tools_beside_canvas && !self.ui.toolbar_right) || self.ui.toolbar_pos.is_some()) { toolbar::show(self, ui); } else if !self.ui.toolbar && self.ui.screen_mode < 3 && self.ui.tab_hid.is_none() { // Window › Tools hides the Tools panel alone; Tab hides the toolbars made with New diff --git a/crates/ui-egui/src/edit_toolbar.rs b/crates/ui-egui/src/edit_toolbar.rs index 1a4c54989..2d6fede3b 100644 --- a/crates/ui-egui/src/edit_toolbar.rs +++ b/crates/ui-egui/src/edit_toolbar.rs @@ -467,7 +467,7 @@ pub(crate) fn drawer(app: &mut VectorcraftApp, ctx: &egui::Context) { let screen = ctx.content_rect(); let id = drawer_id(); let size = ctx.memory(|m| m.area_rect(id)).map_or(vec2(WIDTH, 200.0), |r| r.size()); - let x = (bar.right() + GAP).min(screen.right() - size.x - GAP).max(screen.left()); + let x = crate::toolbar::beside(bar, size.x, GAP, crate::toolbar::room(app, ctx).shrink(GAP)); // Never above the toolbar's top: higher up are the window's title bar (and on macOS its // buttons) and the bars under it. let top = bar.top().max(screen.top() + GAP); diff --git a/crates/ui-egui/src/i18n/bg.tsv b/crates/ui-egui/src/i18n/bg.tsv index 99d07134f..15374b930 100644 --- a/crates/ui-egui/src/i18n/bg.tsv +++ b/crates/ui-egui/src/i18n/bg.tsv @@ -3928,7 +3928,7 @@ axis Both И двете Dock to Bottom Закотвяне долу Dock Control Bar Закотвяне на контролната лента Drag to float the toolbar Плъзнете, за да направите лентата с инструменти плаваща - Drag to the window's left edge to dock Плъзнете до левия ръб на прозореца за закотвяне + Drag to the window's left or right edge to dock Плъзнете до левия или десния ръб на прозореца за закотвяне Float Tool Group Плаваща група инструменти @msg no library `{id}` няма библиотека `{id}` @msg select some type first първо изберете текст @@ -6426,3 +6426,4 @@ breakText Glyphs Глифи # Align to Pixel Grid Align to Pixel Grid Подравняване към пикселната мрежа +@msg side is left or right, not `{s}` side е left или right, а не `{s}` diff --git a/crates/ui-egui/src/i18n/bs.tsv b/crates/ui-egui/src/i18n/bs.tsv index 8e931292f..101f5632f 100644 --- a/crates/ui-egui/src/i18n/bs.tsv +++ b/crates/ui-egui/src/i18n/bs.tsv @@ -1269,7 +1269,7 @@ lighting Light Svjetlo X: X: Y: Y: Drag to float the toolbar Prevucite da odvojite traku s alatima - Drag to the window's left edge to dock Prevucite do lijeve ivice prozora za sidrenje + Drag to the window's left or right edge to dock Prevucite do lijeve ili desne ivice prozora za sidrenje Crystallize Kristalizuj Add Anchor Point Tool Alat za dodavanje sidrene tačke Anchor Point Tool Alat sidrena tačka @@ -6475,3 +6475,4 @@ shape Open Otvoren # Align to Pixel Grid Align to Pixel Grid Poravnaj s mrežom piksela +@msg side is left or right, not `{s}` side je left ili right, a ne `{s}` diff --git a/crates/ui-egui/src/i18n/ca.tsv b/crates/ui-egui/src/i18n/ca.tsv index 88c5819a1..0ad7a05b9 100644 --- a/crates/ui-egui/src/i18n/ca.tsv +++ b/crates/ui-egui/src/i18n/ca.tsv @@ -1253,7 +1253,7 @@ antiAlias Sharp Nítid Drag to float as a toolbar Arrossega per surar com a barra d’eines Drag to float the toolbar Arrossega per fer surar la barra d’eines Drag to move Arrossega per moure - Drag to the window's left edge to dock Arrossega fins a la vora esquerra de la finestra per acoblar + Drag to the window's left or right edge to dock Arrossega fins a la vora esquerra o dreta de la finestra per acoblar Drag values or labels. Double-click a value to type. Arrossega els valors o les etiquetes. Fes doble clic en un valor per escriure’l. Draw Dibuixa Draw Behind Dibuixa al darrere @@ -6637,3 +6637,4 @@ breakText Glyphs Glifs # Align to Pixel Grid Align to Pixel Grid Alinea a la quadrícula de píxels @msg only paths and compound paths can be aligned to the pixel grid només els traçats i els traçats compostos es poden alinear a la quadrícula de píxels +@msg side is left or right, not `{s}` side ha de ser left o right, no `{s}` diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 9af7d8e50..f4f6a01f8 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -1289,7 +1289,7 @@ lighting Light Světlo X: X: Y: Y: Drag to float the toolbar Přetažením vytvoříte plovoucí panel nástrojů - Drag to the window's left edge to dock Přetažením k levému okraji okna panel ukotvíte + Drag to the window's left or right edge to dock Přetažením k levému nebo pravému okraji okna panel ukotvíte # Tools Crystallize Krystalizace @@ -6656,3 +6656,4 @@ breakText Glyphs Glyfy # Align to Pixel Grid Align to Pixel Grid Zarovnat na mřížku obrazových bodů @msg only paths and compound paths can be aligned to the pixel grid na mřížku obrazových bodů lze zarovnat jen cesty a složené cesty +@msg side is left or right, not `{s}` side je left nebo right, ne `{s}` diff --git a/crates/ui-egui/src/i18n/da.tsv b/crates/ui-egui/src/i18n/da.tsv index 5c6cac613..3095b6477 100644 --- a/crates/ui-egui/src/i18n/da.tsv +++ b/crates/ui-egui/src/i18n/da.tsv @@ -1204,7 +1204,7 @@ lighting Light Lys X: X: Y: Y: Drag to float the toolbar Træk for at frigøre værktøjslinjen - Drag to the window's left edge to dock Træk til vinduets venstre kant for at fastgøre + Drag to the window's left or right edge to dock Træk til vinduets venstre eller højre kant for at fastgøre Crystallize Krystallisér Add Anchor Point Tool Tilføj ankerpunkt-værktøj Anchor Point Tool Ankerpunktværktøj @@ -6440,3 +6440,4 @@ breakText Glyphs Glyffer # Align to Pixel Grid Align to Pixel Grid Juster efter pixelgitter +@msg side is left or right, not `{s}` side er left eller right, ikke `{s}` diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index 0c494018e..0747c8aba 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -3937,7 +3937,7 @@ theme Appearance Erscheinungsbild Dock to Bottom Unten andocken Dock Control Bar Steuerungsleiste andocken Drag to float the toolbar Ziehen, um die Werkzeugleiste abzulösen - Drag to the window's left edge to dock Zum Andocken an den linken Fensterrand ziehen + Drag to the window's left or right edge to dock Zum Andocken an den linken oder rechten Fensterrand ziehen Float Tool Group Werkzeuggruppe ablösen # Status and error messages (`@msg`), translated where the status bar shows them; the message itself @@ -6243,3 +6243,4 @@ breakText Glyphs Glyphen # Align to Pixel Grid Align to Pixel Grid Am Pixelraster ausrichten @msg only paths and compound paths can be aligned to the pixel grid nur Pfade und zusammengesetzte Pfade können am Pixelraster ausgerichtet werden +@msg side is left or right, not `{s}` side ist left oder right, nicht `{s}` diff --git a/crates/ui-egui/src/i18n/el.tsv b/crates/ui-egui/src/i18n/el.tsv index cc38cad02..fdcebaee2 100644 --- a/crates/ui-egui/src/i18n/el.tsv +++ b/crates/ui-egui/src/i18n/el.tsv @@ -4145,7 +4145,7 @@ digits Malayalam Μαλαγιάλαμ Drag to float as a toolbar Σύρετε για αποδέσμευση ως γραμμή εργαλείων Put back in the toolbar Επαναφορά στη γραμμή εργαλείων Drag to float the toolbar Σύρετε για αποδέσμευση της γραμμής εργαλείων - Drag to the window's left edge to dock Σύρετε στο αριστερό άκρο του παραθύρου για σύνδεση + Drag to the window's left or right edge to dock Σύρετε στο αριστερό ή στο δεξί άκρο του παραθύρου για σύνδεση Float Tool Group Αποδέσμευση ομάδας εργαλείων @msg a PostScript error ({name} in `{op}`) σφάλμα PostScript ({name} στην εντολή `{op}`) @msg a PostScript error ({name} in `{op}`), in {procs} σφάλμα PostScript ({name} στην εντολή `{op}`), στις διαδικασίες {procs} @@ -6608,3 +6608,4 @@ breakText Glyphs Γλύφοι # Align to Pixel Grid Align to Pixel Grid Στοίχιση στο πλέγμα εικονοστοιχείων @msg only paths and compound paths can be aligned to the pixel grid μόνο διαδρομές και σύνθετες διαδρομές μπορούν να στοιχιστούν στο πλέγμα εικονοστοιχείων +@msg side is left or right, not `{s}` το side είναι left ή right, όχι `{s}` diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index fa3f9290d..035bdceb6 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -4022,7 +4022,7 @@ axis Both Ambos Dock to Bottom Anclar abajo Dock Control Bar Anclar barra de control Drag to float the toolbar Arrastrar para hacer flotar la barra de herramientas - Drag to the window's left edge to dock Arrastrar al borde izquierdo de la ventana para anclar + Drag to the window's left or right edge to dock Arrastrar al borde izquierdo o derecho de la ventana para anclar Float Tool Group Hacer flotar el grupo de herramientas # Status and error messages (`@msg`), translated where the status bar shows them; the message itself @@ -6599,3 +6599,4 @@ breakText Glyphs Glifos # Align to Pixel Grid Align to Pixel Grid Alinear con cuadrícula de píxeles @msg only paths and compound paths can be aligned to the pixel grid solo los trazados y los trazados compuestos se pueden alinear con la cuadrícula de píxeles +@msg side is left or right, not `{s}` side es left o right, no `{s}` diff --git a/crates/ui-egui/src/i18n/fi.tsv b/crates/ui-egui/src/i18n/fi.tsv index eaf0c103d..b2104d773 100644 --- a/crates/ui-egui/src/i18n/fi.tsv +++ b/crates/ui-egui/src/i18n/fi.tsv @@ -1267,7 +1267,7 @@ lighting Light Valo X: X: Y: Y: Drag to float the toolbar Kelluta työkaluriviä vetämällä - Drag to the window's left edge to dock Telakoi vetämällä ikkunan vasempaan reunaan + Drag to the window's left or right edge to dock Telakoi vetämällä ikkunan vasempaan tai oikeaan reunaan Crystallize Kiteytä Add Anchor Point Tool Lisää ankkuripiste -työkalu Anchor Point Tool Ankkuripistetyökalu @@ -6691,3 +6691,4 @@ breakText Glyphs Merkit # Align to Pixel Grid Align to Pixel Grid Tasaa pikseliruudukkoon @msg only paths and compound paths can be aligned to the pixel grid vain polut ja yhdistelmäpolut voi tasata pikseliruudukkoon +@msg side is left or right, not `{s}` side on left tai right, ei `{s}` diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index b6d9da760..5820de83a 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -4011,7 +4011,7 @@ axis Both Les deux Dock to Bottom Ancrer en bas Dock Control Bar Ancrer la barre de contrôle Drag to float the toolbar Faire glisser pour rendre la barre d’outils flottante - Drag to the window's left edge to dock Faire glisser vers le bord gauche de la fenêtre pour ancrer + Drag to the window's left or right edge to dock Faire glisser vers le bord gauche ou droit de la fenêtre pour ancrer Float Tool Group Rendre le groupe d’outils flottant # Status and error messages (`@msg`), translated where the status bar shows them; the message itself @@ -6651,3 +6651,4 @@ breakText Glyphs Glyphes # Align to Pixel Grid Align to Pixel Grid Aligner sur la grille de pixels @msg only paths and compound paths can be aligned to the pixel grid seuls les tracés et les tracés transparents peuvent être alignés sur la grille de pixels +@msg side is left or right, not `{s}` side vaut left ou right, pas `{s}` diff --git a/crates/ui-egui/src/i18n/hi.tsv b/crates/ui-egui/src/i18n/hi.tsv index c972e3e79..a6ce918ab 100644 --- a/crates/ui-egui/src/i18n/hi.tsv +++ b/crates/ui-egui/src/i18n/hi.tsv @@ -1384,7 +1384,7 @@ antiAlias Sharp शार्प Drag to float as a toolbar एक टूलबार के रूप में तैरने के लिए खींचें Drag to float the toolbar टूलबार को तैरने के लिए खींचें Drag to move आगे बढ़ने के लिए - Drag to the window's left edge to dock खिड़की के बाएं किनारे पर डॉक करने के लिए खींचें + Drag to the window's left or right edge to dock खिड़की के बाएं या दाएं किनारे पर डॉक करने के लिए खींचें Drag values or labels. Double-click a value to type. मूल्यों या लेबल खींचें। टाइप करने के लिए एक मान को डबल क्लिक करें। Draw ड्रा Draw Behind पीछे खींचना @@ -8098,3 +8098,4 @@ theme Appearance अपीयरेंस @msg the file is larger than the {MAX_INPUT_BYTES} bytes an importer reads फ़ाइल उन {MAX_INPUT_BYTES} बाइट्स से बड़ी है जो इंपोर्टर पढ़ता है @msg an importer declares 1 to {MAX_EXTENSIONS} `extensions` इंपोर्टर 1 से {MAX_EXTENSIONS} `extensions` घोषित करता है @msg an importer always gets an import's budget: leave `budget` out इंपोर्टर को हमेशा इंपोर्ट का बजट मिलता है: `budget` छोड़ दें +@msg side is left or right, not `{s}` side left या right होना चाहिए, `{s}` नहीं diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index 82de11af4..076565e8c 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -1161,7 +1161,7 @@ font-technology Variable Változó Drag to float as a toolbar Húzd el, hogy önálló eszköztárként lebegjen Drag to float the toolbar Húzd el az eszköztár lebegtetéséhez Drag to move Húzással áthelyezhető - Drag to the window's left edge to dock Dokkoláshoz húzd az ablak bal szélére + Drag to the window's left or right edge to dock Dokkoláshoz húzd az ablak bal vagy jobb szélére Step up or down Léptetés fel vagy le Drag values or labels. Double-click a value to type. Húzd az értékeket vagy a címkéket. Gépeléshez kattints duplán egy értékre. Draw Rajzolás @@ -6640,3 +6640,4 @@ breakText Glyphs Glifák # Align to Pixel Grid Align to Pixel Grid Igazítás a pixelrácshoz @msg only paths and compound paths can be aligned to the pixel grid csak útvonalak és összetett útvonalak igazíthatók a pixelrácshoz +@msg side is left or right, not `{s}` a side értéke left vagy right lehet, nem `{s}` diff --git a/crates/ui-egui/src/i18n/id.tsv b/crates/ui-egui/src/i18n/id.tsv index 00b343156..b56e8d7e6 100644 --- a/crates/ui-egui/src/i18n/id.tsv +++ b/crates/ui-egui/src/i18n/id.tsv @@ -1204,7 +1204,7 @@ lighting Light Cahaya X: X: Y: Y: Drag to float the toolbar Seret untuk mengambangkan bilah alat - Drag to the window's left edge to dock Seret ke tepi kiri jendela untuk memasang + Drag to the window's left or right edge to dock Seret ke tepi kiri atau kanan jendela untuk memasang Crystallize Kristalisasi Add Anchor Point Tool Alat tambah titik jangkar Anchor Point Tool Alat titik jangkar @@ -6440,3 +6440,4 @@ breakText Glyphs Glif # Align to Pixel Grid Align to Pixel Grid Sejajarkan ke grid piksel +@msg side is left or right, not `{s}` side adalah left atau right, bukan `{s}` diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index 1610413fb..9f731a6a9 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -4064,7 +4064,7 @@ axis Both Entrambi Dock to Bottom Ancora in basso Dock Control Bar Ancora barra di controllo Drag to float the toolbar Trascina per rendere mobile la barra degli strumenti - Drag to the window's left edge to dock Trascina sul bordo sinistro della finestra per ancorare + Drag to the window's left or right edge to dock Trascina sul bordo sinistro o destro della finestra per ancorare Float Tool Group Rendi mobile gruppo strumenti # Status and error messages (`@msg`), translated where the status bar shows them; the message itself @@ -6277,3 +6277,4 @@ breakText Glyphs Glifi # Align to Pixel Grid Align to Pixel Grid Allinea alla griglia pixel @msg only paths and compound paths can be aligned to the pixel grid solo i tracciati e i tracciati composti possono essere allineati alla griglia pixel +@msg side is left or right, not `{s}` side è left o right, non `{s}` diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv index 1e76e79a8..7a943b24c 100644 --- a/crates/ui-egui/src/i18n/ja.tsv +++ b/crates/ui-egui/src/i18n/ja.tsv @@ -4006,7 +4006,7 @@ axis Both 両方 Dock to Bottom 下部にドッキング Dock Control Bar コントロールバーをドッキング Drag to float the toolbar ドラッグしてツールバーをフローティング - Drag to the window's left edge to dock ウィンドウの左端までドラッグしてドッキング + Drag to the window's left or right edge to dock ウィンドウの左端または右端までドラッグしてドッキング Float Tool Group ツールグループをフローティング # The macOS menu bar (native_menu): the app and Window menus' system items, Settings pages. @@ -6342,3 +6342,4 @@ breakText Glyphs 字形 # Align to Pixel Grid Align to Pixel Grid ピクセルグリッドに整合 @msg only paths and compound paths can be aligned to the pixel grid ピクセルグリッドに整合できるのはパスと複合パスのみです +@msg side is left or right, not `{s}` side は left または right です(`{s}` ではありません) diff --git a/crates/ui-egui/src/i18n/ka.tsv b/crates/ui-egui/src/i18n/ka.tsv index bbde307d1..1efebf897 100644 --- a/crates/ui-egui/src/i18n/ka.tsv +++ b/crates/ui-egui/src/i18n/ka.tsv @@ -1144,7 +1144,7 @@ lighting Light სინათლე Toggle single/double column ერთი/ორი სვეტის გადართვა W: სიგ.: Drag to float the toolbar გადაათრიეთ ხელსაწყოთა ზოლის მცურავად გადასაქცევად - Drag to the window's left edge to dock მისამაგრებლად გადაათრიეთ ფანჯრის მარცხენა კიდესთან + Drag to the window's left or right edge to dock მისამაგრებლად გადაათრიეთ ფანჯრის მარცხენა ან მარჯვენა კიდესთან Crystallize კრისტალიზაცია Add Anchor Point Tool საყრდენი წერტილის დამატების ხელსაწყო Anchor Point Tool საყრდენი წერტილის ხელსაწყო @@ -6717,3 +6717,4 @@ font-script Japanese იაპონური # Align to Pixel Grid Align to Pixel Grid პიქსელურ ბადეზე გასწორება @msg only paths and compound paths can be aligned to the pixel grid პიქსელურ ბადეზე მხოლოდ ტრაექტორიების და შედგენილი ტრაექტორიების გასწორებაა შესაძლებელი +@msg side is left or right, not `{s}` side არის left ან right და არა `{s}` diff --git a/crates/ui-egui/src/i18n/ko.tsv b/crates/ui-egui/src/i18n/ko.tsv index c1da3da08..a98e905e1 100644 --- a/crates/ui-egui/src/i18n/ko.tsv +++ b/crates/ui-egui/src/i18n/ko.tsv @@ -3990,7 +3990,7 @@ axis Both 양쪽 Dock to Bottom 아래쪽에 고정 Dock Control Bar 컨트롤 막대 고정 Drag to float the toolbar 드래그하여 도구 모음 분리 - Drag to the window's left edge to dock 창 왼쪽 가장자리로 드래그하여 고정 + Drag to the window's left or right edge to dock 창 왼쪽 또는 오른쪽 가장자리로 드래그하여 고정 Float Tool Group 도구 그룹 분리 Services 서비스 Hide VectorCraft VectorCraft 숨기기 @@ -6238,3 +6238,4 @@ breakText Glyphs 글리프 # Align to Pixel Grid Align to Pixel Grid 픽셀 격자에 정렬 @msg only paths and compound paths can be aligned to the pixel grid 패스와 컴파운드 패스만 픽셀 격자에 정렬할 수 있습니다 +@msg side is left or right, not `{s}` side는 left 또는 right입니다(`{s}` 아님) diff --git a/crates/ui-egui/src/i18n/nl.tsv b/crates/ui-egui/src/i18n/nl.tsv index b5d8f750a..93b9371ee 100644 --- a/crates/ui-egui/src/i18n/nl.tsv +++ b/crates/ui-egui/src/i18n/nl.tsv @@ -1218,7 +1218,7 @@ lighting Light Licht X: X: Y: Y: Drag to float the toolbar Sleep om de werkbalk zwevend te maken - Drag to the window's left edge to dock Sleep naar de linkerrand van het venster om te dokken + Drag to the window's left or right edge to dock Sleep naar de linker- of rechterrand van het venster om te dokken Crystallize Kristalliseren Add Anchor Point Tool Ankerpunt toevoegen Anchor Point Tool Ankerpunt-gereedschap @@ -6491,3 +6491,4 @@ breakText Glyphs Glyphs # Align to Pixel Grid Align to Pixel Grid Uitlijnen op pixelraster +@msg side is left or right, not `{s}` side is left of right, niet `{s}` diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv index a78055e25..61ae817ef 100644 --- a/crates/ui-egui/src/i18n/pl.tsv +++ b/crates/ui-egui/src/i18n/pl.tsv @@ -1217,7 +1217,7 @@ lighting Light Światło Toggle single/double column Przełącz jedną/dwie kolumny W: S: Drag to float the toolbar Przeciągnij, aby odpiąć pasek narzędzi - Drag to the window's left edge to dock Przeciągnij do lewej krawędzi okna, aby zadokować + Drag to the window's left or right edge to dock Przeciągnij do lewej lub prawej krawędzi okna, aby zadokować Crystallize Krystalizacja Add Anchor Point Tool Narzędzie Dodaj punkt kontrolny Anchor Point Tool Narzędzie Punkt kontrolny @@ -6512,3 +6512,4 @@ breakText Glyphs Glify # Align to Pixel Grid Align to Pixel Grid Wyrównaj do siatki pikseli @msg only paths and compound paths can be aligned to the pixel grid do siatki pikseli można wyrównać tylko ścieżki i ścieżki złożone +@msg side is left or right, not `{s}` side to left lub right, a nie `{s}` diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv index f0e40aeb9..922d408ed 100644 --- a/crates/ui-egui/src/i18n/pt-br.tsv +++ b/crates/ui-egui/src/i18n/pt-br.tsv @@ -3610,7 +3610,7 @@ axis Horizontal Horizontal axis Vertical Vertical axis Both Ambos Drag to float the toolbar Arraste para flutuar a barra de ferramentas - Drag to the window's left edge to dock Arraste até a borda esquerda da janela para encaixar + Drag to the window's left or right edge to dock Arraste até a borda esquerda ou direita da janela para encaixar @msg no library `{id}` nenhuma biblioteca `{id}` @msg select some type first selecione algum texto primeiro @msg kerning must be a number, "auto", or "optical" O kerning deve ser um número, “auto” ou “optical” @@ -6729,3 +6729,4 @@ swatch Yellow Green Verde-amarelado # Align to Pixel Grid Align to Pixel Grid Alinhar à Grade de Pixels @msg only paths and compound paths can be aligned to the pixel grid somente caminhos e caminhos compostos podem ser alinhados à grade de pixels +@msg side is left or right, not `{s}` side é left ou right, não `{s}` diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index 9f5f728b0..b3c66d0f8 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -4058,7 +4058,7 @@ axis Both Оба Dock to Bottom Прикрепить снизу Dock Control Bar Прикрепить панель управления Drag to float the toolbar Перетащите, чтобы сделать панель инструментов плавающей - Drag to the window's left edge to dock Перетащите к левому краю окна для прикрепления + Drag to the window's left or right edge to dock Перетащите к левому или правому краю окна для прикрепления Float Tool Group Сделать группу инструментов плавающей # Status and error messages (`@msg`), translated where the status bar shows them; the message itself @@ -6745,3 +6745,4 @@ shape Open Открытый # Align to Pixel Grid Align to Pixel Grid Выровнять по пиксельной сетке @msg only paths and compound paths can be aligned to the pixel grid по пиксельной сетке можно выровнять только контуры и составные контуры +@msg side is left or right, not `{s}` side — это left или right, а не `{s}` diff --git a/crates/ui-egui/src/i18n/sv.tsv b/crates/ui-egui/src/i18n/sv.tsv index 7ef0f5e8d..bae0b3f7e 100644 --- a/crates/ui-egui/src/i18n/sv.tsv +++ b/crates/ui-egui/src/i18n/sv.tsv @@ -3938,7 +3938,7 @@ axis Both Båda Dock to Bottom Docka nederst Dock Control Bar Docka kontrollfältet Drag to float the toolbar Dra för att göra verktygsfältet flytande - Drag to the window's left edge to dock Dra till fönstrets vänsterkant för att docka + Drag to the window's left or right edge to dock Dra till fönstrets vänster- eller högerkant för att docka Float Tool Group Gör verktygsgruppen flytande @msg no library `{id}` inget bibliotek `{id}` @msg select some type first markera någon text först @@ -8141,3 +8141,4 @@ digits Hindi Hindi # Align to Pixel Grid Align to Pixel Grid Justera mot pixelrutnät @msg only paths and compound paths can be aligned to the pixel grid bara banor och sammansatta banor kan justeras mot pixelrutnätet +@msg side is left or right, not `{s}` side är left eller right, inte `{s}` diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv index 26264b594..6a62f228b 100644 --- a/crates/ui-egui/src/i18n/tr.tsv +++ b/crates/ui-egui/src/i18n/tr.tsv @@ -3824,7 +3824,7 @@ axis Both Her İkisi Dock to Bottom Alta yerleştir Dock Control Bar Kontrol çubuğunu yerleştir Drag to float the toolbar Araç çubuğunu ayırmak için sürükleyin - Drag to the window's left edge to dock Sabitlemek için pencerenin sol kenarına sürükleyin + Drag to the window's left or right edge to dock Sabitlemek için pencerenin sol veya sağ kenarına sürükleyin Float Tool Group Araç Grubunu Yüzer Yap @msg no library `{id}` `{id}` kütüphanesi yok @msg select some type first önce bir tür seçin @@ -6612,3 +6612,4 @@ breakText Glyphs Glifler # Align to Pixel Grid Align to Pixel Grid Piksel Izgarasına Hizala @msg only paths and compound paths can be aligned to the pixel grid piksel ızgarasına yalnızca yollar ve bileşik yollar hizalanabilir +@msg side is left or right, not `{s}` side left veya right olmalıdır, `{s}` değil diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index 824475c52..f4b29e59b 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -4053,7 +4053,7 @@ axis Both Обидві Dock to Bottom Прикріпити внизу Dock Control Bar Прикріпити панель керування Drag to float the toolbar Перетягніть, щоб від’єднати панель інструментів - Drag to the window's left edge to dock Перетягніть до лівого краю вікна для прикріплення + Drag to the window's left or right edge to dock Перетягніть до лівого або правого краю вікна для прикріплення Float Tool Group Від’єднати групу інструментів @msg no library `{id}` немає бібліотеки `{id}` @msg select some type first спочатку виділіть текст @@ -6257,3 +6257,4 @@ breakText Glyphs Гліфи # Align to Pixel Grid Align to Pixel Grid Вирівняти за піксельною сіткою @msg only paths and compound paths can be aligned to the pixel grid за піксельною сіткою можна вирівняти лише контури і складені контури +@msg side is left or right, not `{s}` side — це left або right, а не `{s}` diff --git a/crates/ui-egui/src/i18n/vi.tsv b/crates/ui-egui/src/i18n/vi.tsv index 6e2a9e33f..dadb37d21 100644 --- a/crates/ui-egui/src/i18n/vi.tsv +++ b/crates/ui-egui/src/i18n/vi.tsv @@ -1045,7 +1045,7 @@ font-technology Variable Biến thiên Drag to float as a toolbar Kéo để thả nổi thanh công cụ Drag to float the toolbar Kéo để thả nổi thanh công cụ Drag to move Kéo để di chuyển - Drag to the window's left edge to dock Kéo đến cạnh trái cửa sổ để neo + Drag to the window's left or right edge to dock Kéo đến cạnh trái hoặc phải cửa sổ để neo Step up or down Tăng hoặc giảm một bước Drag values or labels. Double-click a value to type. Kéo giá trị hoặc nhãn. Bấm đúp vào giá trị để nhập. Draw Vẽ @@ -6258,3 +6258,4 @@ breakText Glyphs Glyph # Align to Pixel Grid Align to Pixel Grid Căn theo lưới pixel @msg only paths and compound paths can be aligned to the pixel grid chỉ đường dẫn và đường dẫn phức mới căn theo lưới pixel được +@msg side is left or right, not `{s}` side là left hoặc right, không phải `{s}` diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv index 792919c6a..8b2456f65 100644 --- a/crates/ui-egui/src/i18n/zh-hans.tsv +++ b/crates/ui-egui/src/i18n/zh-hans.tsv @@ -5146,7 +5146,7 @@ axis Both 两者 Dock to Bottom 停放到底部 Dock Control Bar 停放控制栏 Drag to float the toolbar 拖动以浮动工具栏 - Drag to the window's left edge to dock 拖到窗口左边缘以停放 + Drag to the window's left or right edge to dock 拖到窗口左边缘或右边缘以停放 Float Tool Group 浮动工具组 # The macOS menu bar (native_menu): the app and Window menus' system items, Settings pages. @@ -6497,3 +6497,4 @@ breakText Glyphs 字形 # Align to Pixel Grid Align to Pixel Grid 对齐像素网格 @msg only paths and compound paths can be aligned to the pixel grid 只有路径和复合路径可以对齐像素网格 +@msg side is left or right, not `{s}` side 应为 left 或 right,而不是 `{s}` diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index 569c72914..a1da1f933 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -4969,7 +4969,7 @@ axis Both 兩者 Dock to Bottom 停駐到底部 Dock Control Bar 停駐控制列 Drag to float the toolbar 拖曳以浮動工具列 - Drag to the window's left edge to dock 拖曳到視窗左側邊緣以停駐 + Drag to the window's left or right edge to dock 拖曳到視窗左側或右側邊緣以停駐 Float Tool Group 浮動工具組 # The macOS menu bar (native_menu): the app and Window menus' system items, Settings pages. @@ -6295,3 +6295,4 @@ breakText Glyphs 字符 # Align to Pixel Grid Align to Pixel Grid 對齊像素格點 @msg only paths and compound paths can be aligned to the pixel grid 只有路徑和複合路徑可以對齊像素格點 +@msg side is left or right, not `{s}` side 應為 left 或 right,而不是 `{s}` diff --git a/crates/ui-egui/src/menus/ui_commands.rs b/crates/ui-egui/src/menus/ui_commands.rs index 81ae58673..c3af44d3d 100644 --- a/crates/ui-egui/src/menus/ui_commands.rs +++ b/crates/ui-egui/src/menus/ui_commands.rs @@ -615,7 +615,7 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[ "window.panel.dock", "Dock Panel", "", - "{panel: id or \"tools\", anchor?: id, zone?: tab|center|left|right|top|bottom|above|below, before?: id, group?: bool, column?: bool or n, side?: Start|End, onto?: id, above?: id, below?: id, icon?: bool, collapsed?: bool} dock a panel (with `group`, its whole group): with no destination a floating panel goes back where it floated from (else joins the first dock group) and a hidden one shows where it was; with `anchor` (or `onto`) in the group holding that panel, `zone` as for window.panel.move; with `side`, as a new innermost column of that dock (`column: true` then moves its whole dock column or floating window); `column: n` with no other destination docks its group, or the whole floating window it floats in, as a new dock column at that place (1: next to the icon column, counting inwards; `true`: innermost); `icon: true` puts it in a row of its own at the end of the icon column; `above` / `below` as a group of its own above or below the group holding that panel. `collapsed` then minimizes or restores its group. \"tools\" docks the Tools panel at the left edge of the window, or beside the canvas inside any left-side dock while window.toolsBesideCanvas is on. Returns {layout, closed, floating}", + "{panel: id or \"tools\", anchor?: id, zone?: tab|center|left|right|top|bottom|above|below, before?: id, group?: bool, column?: bool or n, side?: Start|End, onto?: id, above?: id, below?: id, icon?: bool, collapsed?: bool} dock a panel (with `group`, its whole group): with no destination a floating panel goes back where it floated from (else joins the first dock group) and a hidden one shows where it was; with `anchor` (or `onto`) in the group holding that panel, `zone` as for window.panel.move; with `side`, as a new innermost column of that dock (`column: true` then moves its whole dock column or floating window); `column: n` with no other destination docks its group, or the whole floating window it floats in, as a new dock column at that place (1: next to the icon column, counting inwards; `true`: innermost); `icon: true` puts it in a row of its own at the end of the icon column; `above` / `below` as a group of its own above or below the group holding that panel. `collapsed` then minimizes or restores its group. \"tools\" docks the Tools panel at the left edge of the window, or beside the canvas inside any left-side dock while window.toolsBesideCanvas is on; with side: right (or End) on the right, between the canvas and the panels, as dropping it there or on the window's right edge does (default: the side it docked at last; left or Start docks it on the left), returning {panel, floating, pos, side}. Returns {layout, closed, floating}", ), ( "window.collapseDock", diff --git a/crates/ui-egui/src/panel_docking/tests.rs b/crates/ui-egui/src/panel_docking/tests.rs index 98c625743..5eba37c31 100644 --- a/crates/ui-egui/src/panel_docking/tests.rs +++ b/crates/ui-egui/src/panel_docking/tests.rs @@ -284,6 +284,45 @@ fn the_tools_panel_floats_by_its_title_bar_and_docks_on_the_left_edge() { assert_eq!(h.app.ui.toolbar_pos, None, "dropped on the left edge, it docks"); } +/// The Tools panel also docks on the right, left of the panels: dropped on the window's right edge +/// it stands between the canvas and the panels, its flyouts open toward the canvas, the side is +/// kept with the preferences, and it drags back to the left edge. +#[test] +fn the_tools_panel_docks_on_the_right_left_of_the_panels() { + let mut h = Harness::new(); + let zone = docked_tools(&h); + h.drag(zone.min + vec2(20.0, 12.0), pos2(600.0, 400.0)); + let [x, y] = h.app.ui.toolbar_pos.expect("the Tools panel floats"); + h.drag(pos2(x + 20.0, y + 7.0), pos2(SCREEN.right() - 10.0, 500.0)); + assert_eq!((h.app.ui.toolbar_pos, h.app.ui.toolbar_right), (None, true), "dropped on the right edge, it docks on the right"); + settle(&mut h); + let bar = docked_tools(&h); + let canvas = h.app.canvas_rect.expect("the canvas"); + let layers = h.tab("layers").expect("the Layers panel, docked right"); + assert!(canvas.right() <= bar.left() + 1.0 && bar.right() <= layers.left() + 1.0, "canvas {canvas:?}, Tools {bar:?}, Layers {layers:?}"); + assert!(SCREEN.right() - bar.right() > 100.0, "the panels keep the window's right edge: {bar:?}"); + // Its flyouts and drawer open toward the canvas, not over the panels. + let room = crate::toolbar::room(&h.app, &h.ctx); + assert!(room.right() <= bar.right() + 0.5, "{room:?}"); + let left = crate::toolbar::beside(bar, 160.0, 8.0, room); + assert!(left + 160.0 <= bar.left() - 7.0, "left of the toolbar: {left}"); + let prefs: crate::state::UiState = serde_json::from_slice(&serde_json::to_vec(&h.app.ui).unwrap()).unwrap(); + assert!(prefs.toolbar_right, "kept with the preferences"); + // Dragged back to the window's left edge, it docks there again. + h.drag(bar.min + vec2(20.0, 12.0), pos2(600.0, 400.0)); + let [x, y] = h.app.ui.toolbar_pos.expect("floats again"); + h.drag(pos2(x + 20.0, y + 7.0), pos2(12.0, 500.0)); + assert_eq!((h.app.ui.toolbar_pos, h.app.ui.toolbar_right), (None, false)); + settle(&mut h); + assert!(docked_tools(&h).left() < 10.0, "at the window's left edge again"); + // Agents: window.panel.dock takes the side (left/right, or Start/End as panels do). + let r = h.app.run("window.panel.dock", json!({"panel": "tools", "side": "End"})).unwrap(); + assert_eq!((r["side"].as_str(), h.app.ui.toolbar_right), (Some("right"), true)); + h.app.run("window.panel.float", json!({"panel": "tools"})).unwrap(); + assert_eq!(h.app.run("window.panel.dock", json!({"panel": "tools"})).unwrap()["side"], "right", "back on the side it docked at last"); + assert!(h.app.run("window.panel.dock", json!({"panel": "tools", "side": "top"})).is_err()); +} + /// The docked Tools panel as last drawn. fn docked_tools(h: &Harness) -> Rect { h.ctx.data(|d| d.get_temp::(crate::toolbar::docked_rect_id())).expect("the docked Tools panel") diff --git a/crates/ui-egui/src/state.rs b/crates/ui-egui/src/state.rs index 53046a5a8..95ffcd9cd 100644 --- a/crates/ui-egui/src/state.rs +++ b/crates/ui-egui/src/state.rs @@ -473,6 +473,11 @@ pub struct UiState { /// `window.toolsBesideCanvas`). Off by default, and off in state saved without it. #[serde(default)] pub tools_beside_canvas: bool, + /// The docked Tools panel stands on the right, between the canvas and the panels, instead of on + /// the left (dropped there, or `window.panel.dock {panel: "tools", side: "right"}`). Off by + /// default, and off in state saved without it. + #[serde(default)] + pub toolbar_right: bool, pub status_bar: bool, pub help_bar: bool, pub dock: bool, @@ -1010,6 +1015,7 @@ impl Default for UiState { dock_width: None, toolbar_pos: None, tools_beside_canvas: false, + toolbar_right: false, status_bar: true, help_bar: true, dock: true, diff --git a/crates/ui-egui/src/toolbar.rs b/crates/ui-egui/src/toolbar.rs index dce5912ba..6a90cdfac 100644 --- a/crates/ui-egui/src/toolbar.rs +++ b/crates/ui-egui/src/toolbar.rs @@ -16,7 +16,7 @@ use crate::theme::{self, Tokens}; use crate::{VectorcraftApp, icons, widgets}; pub(crate) const PITCH: f32 = 30.0; -const WIDTH: f32 = 48.0; +pub(crate) const WIDTH: f32 = 48.0; /// Seconds a press on a tool group's button is held before its flyout opens. const LONG_PRESS: f64 = 0.35; /// Width of the grab bar down a flyout's right side: dragging it tears the flyout off. @@ -105,21 +105,39 @@ fn panel_width(ui: &crate::state::UiState) -> f32 { } /// Space reserved inside the protected canvas panel for a visible Tools panel docked beside the -/// canvas (`UiState::tools_beside_canvas`); none while Tools docks at the window's edge. +/// canvas (`UiState::tools_beside_canvas`) or on the canvas's right (`UiState::toolbar_right`); +/// none while Tools docks at the window's left edge. pub(crate) fn docked_width(ui: &crate::state::UiState) -> f32 { - if ui.tools_beside_canvas && ui.toolbar && ui.screen_mode < 3 && ui.toolbar_pos.is_none() { panel_width(ui) + 6.0 } else { 0.0 } + if (ui.tools_beside_canvas || ui.toolbar_right) && ui.toolbar && ui.screen_mode < 3 && ui.toolbar_pos.is_none() { + panel_width(ui) + 6.0 + } else { + 0.0 + } } /// With `UiState::tools_beside_canvas` on, the canvas-edge redocking target, registered even /// while Tools floats, and the docked panel, which follows the canvas's left edge as dock columns /// resize, collapse or hide. With it off, `app.rs` draws Tools before the docking layout. +/// +/// The canvas's right edge, left of the panels, is a redocking target too, and Tools docked there +/// (`UiState::toolbar_right`) is drawn at it whichever way the setting is. pub(crate) fn show_beside_canvas(app: &mut VectorcraftApp, ui: &mut Ui) { - if app.ui.tools_beside_canvas && app.ui.toolbar && app.ui.screen_mode < 3 { - crate::tools_float::set_dock_zones(ui.ctx(), ui.available_rect_before_wrap(), WIDTH); - if app.ui.toolbar_pos.is_none() { - show(app, ui); - } + if !app.ui.toolbar || app.ui.screen_mode >= 3 { + return; } + let canvas = ui.available_rect_before_wrap(); + crate::tools_float::set_right_dock_zone(ui.ctx(), canvas, WIDTH); + if app.ui.tools_beside_canvas { + crate::tools_float::set_dock_zones(ui.ctx(), canvas, WIDTH); + } + if app.ui.toolbar_pos.is_none() && (app.ui.tools_beside_canvas || app.ui.toolbar_right) { + show(app, ui); + } +} + +/// Is the Tools panel docked on the right, between the canvas and the panels? +pub(crate) fn docked_right(ui: &crate::state::UiState) -> bool { + ui.toolbar_right && ui.toolbar_pos.is_none() } pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) { @@ -131,8 +149,13 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) { let w = panel_width(&app.ui); match app.ui.toolbar_pos { None => { - let margin = egui::Margin { left: 6, right: 0, top: 6, bottom: 6 }; - let docked = egui::Panel::left("toolbar").resizable(false).exact_size(w + 6.0).frame(egui::Frame::NONE).show(ui, |ui| { + // The card's outer gap faces the edge it docks at. + let (panel, margin) = if app.ui.toolbar_right { + (egui::Panel::right("toolbar"), egui::Margin { left: 0, right: 6, top: 6, bottom: 6 }) + } else { + (egui::Panel::left("toolbar"), egui::Margin { left: 6, right: 0, top: 6, bottom: 6 }) + }; + let docked = panel.resizable(false).exact_size(w + 6.0).frame(egui::Frame::NONE).show(ui, |ui| { crate::theme::card(ui, &t, margin, |ui| body(app, ui, cols, None)); }); ui.ctx().data_mut(|d| d.insert_temp(docked_rect_id(), docked.response.rect)); @@ -211,7 +234,7 @@ fn body(app: &mut VectorcraftApp, ui: &mut Ui, cols: usize, floating: Option Option { ctx.input(|i| i.pointer.press_origin().zip(i.pointer.interact_pos()).map(|(a, b)| b - a)) } +/// Where the toolbar's flyouts and drawer may open: the window, or with the toolbar docked right +/// the part left of it, so they open toward the canvas instead of over the panels. +pub(crate) fn room(app: &VectorcraftApp, ctx: &egui::Context) -> egui::Rect { + let mut r = ctx.content_rect(); + if docked_right(&app.ui) + && let Some(x) = ctx.data(|d| d.get_temp::(docked_rect_id())).map(|bar| bar.right()) + { + r.max.x = r.max.x.min(x); + } + r +} + +/// The left edge of something `width` wide opened beside `anchor` (a tool, the toolbar), `gap` +/// from it: on its right when it fits in `screen`, else on its left (a toolbar docked right), +/// kept inside the screen either way. +pub(crate) fn beside(anchor: egui::Rect, width: f32, gap: f32, screen: egui::Rect) -> f32 { + let right = anchor.right() + gap; + let x = if right + width <= screen.right() { right } else { anchor.left() - gap - width }; + x.min(screen.right() - width).max(screen.left()) +} + fn flyout(app: &mut VectorcraftApp, ctx: &egui::Context) { if app.ui.flyout.is_none() { return; @@ -865,12 +909,13 @@ fn flyout(app: &mut VectorcraftApp, ctx: &egui::Context) { let active = app.session.tool_id(); let toolbar = ctx.data(|d| d.get_temp::>(flyout_toolbar_id())).flatten(); let mut input = FlyoutInput::default(); - let resp = egui::Area::new(egui::Id::unique("tool-flyout")).order(egui::Order::Foreground).fixed_pos(anchor.right_top() + vec2(8.0, -1.0)).show( - ctx, - |ui| { + // Beside the tool, on the side with room for it: toward the canvas from a toolbar docked right. + let size = ctx.memory(|m| m.area_rect(egui::Id::unique("tool-flyout"))).map_or(vec2(160.0, 0.0), |r| r.size()); + let x = beside(anchor, size.x, 8.0, room(app, ctx)); + let resp = + egui::Area::new(egui::Id::unique("tool-flyout")).order(egui::Order::Foreground).fixed_pos(pos2(x, anchor.top() - 1.0)).show(ctx, |ui| { flyout_frame(&t, false).show(ui, |ui| input = flyout_body(ui, &t, active, &tools, false, toolbar.as_deref())); - }, - ); + }); // Dragging the bar tears the flyout off, and so does releasing a press over it (a click, or the // end of the long press that opened the flyout): it floats where the pointer is. let at = ctx.input(|i| i.pointer.interact_pos()); diff --git a/crates/ui-egui/src/tools_float.rs b/crates/ui-egui/src/tools_float.rs index 13108368f..2781e4232 100644 --- a/crates/ui-egui/src/tools_float.rs +++ b/crates/ui-egui/src/tools_float.rs @@ -3,11 +3,12 @@ //! docked panel floats it under the pointer, a floating panel's title bar moves it, and a release //! over the strip along the window's left edge (lit up) docks it there. With Keep Tools Beside the //! Canvas on (`UiState::tools_beside_canvas`), a release over the canvas's left edge docks it too, -//! and either release docks it beside the canvas. Escape or losing the window's focus puts it back -//! where the drag began. +//! and either release docks it beside the canvas. A release over the canvas's right edge (left of +//! the panels) or the window's right edge docks it on the right, between the canvas and the panels. +//! Escape or losing the window's focus puts it back where the drag began. //! //! `window.panel.float {panel: "tools"}` / `window.panel.dock {panel: "tools"}` do the same for -//! agents. Its position is kept with the preferences and in user workspaces, and a position saved +//! agents (`side: right` docks it on the right). Its position and side are kept with the preferences and in user workspaces, and a position saved //! on a bigger window is clamped into this one when drawn. use egui::{CornerRadius, Id, Key, Pos2, Rect, Stroke, Vec2, pos2, vec2}; @@ -29,6 +30,8 @@ struct Move { grab: Vec2, from: Pos2, original: Option<[f32; 2]>, + /// The side it was docked on before the drag. + right: bool, } fn move_id() -> Id { @@ -49,6 +52,18 @@ pub(crate) fn tools_zone_id() -> Id { Id::unique("tools-float-zone") } +/// The strip along the canvas's right edge, left of the panels, where the Tools panel docks on the +/// right, as last laid out. +pub(crate) fn tools_zone_right_id() -> Id { + Id::unique("tools-float-zone-right") +} + +/// Accept a drop left of the panels docked right: the canvas's right edge. +pub(crate) fn set_right_dock_zone(ctx: &egui::Context, canvas: Rect, width: f32) { + let zone = Rect::from_min_max(pos2(canvas.right() - width, canvas.top()), canvas.max); + ctx.data_mut(|d| d.insert_temp(tools_zone_right_id(), zone)); +} + fn window_zone_id() -> Id { Id::unique("tools-float-window-zone") } @@ -93,7 +108,7 @@ pub(crate) fn cancel_move_on_escape(app: &mut VectorcraftApp, ctx: &egui::Contex fn start(app: &VectorcraftApp, ctx: &egui::Context, grab: Vec2) { let Some(from) = ctx.input(|i| i.pointer.press_origin().or(i.pointer.interact_pos())) else { return }; - ctx.data_mut(|d| d.insert_temp(move_id(), Move { grab, from, original: app.ui.toolbar_pos })); + ctx.data_mut(|d| d.insert_temp(move_id(), Move { grab, from, original: app.ui.toolbar_pos, right: app.ui.toolbar_right })); } /// The Tools panel's title bar was pressed (`title`, the panel's bounds `bounds`): docked, dragging @@ -116,13 +131,23 @@ pub(crate) fn drag_tools(app: &mut VectorcraftApp, ctx: &egui::Context, title: & } } -/// The docking strip under `at`, if any: the window's left edge, and with `beside_canvas` the -/// canvas's left edge as well. -fn drop_zone(ctx: &egui::Context, at: Pos2, beside_canvas: bool) -> Option { - ctx.data(|d| { +/// The docking strip under `at`, if any, and whether it docks the panel on the right: the window's +/// left edge, with `beside_canvas` the canvas's left edge as well, and on the right the canvas's +/// right edge or anywhere along the window's right edge (which lights up the strip left of the +/// panels, where it docks). +fn drop_zone(ctx: &egui::Context, at: Pos2, beside_canvas: bool) -> Option<(Rect, bool)> { + let (left, right) = ctx.data(|d| { let canvas = d.get_temp::(tools_zone_id()).filter(|_| beside_canvas); - [canvas, d.get_temp::(window_zone_id())].into_iter().flatten().find(|r| r.contains(at)) - }) + let left = [canvas, d.get_temp::(window_zone_id())].into_iter().flatten().find(|r| r.contains(at)); + (left, d.get_temp::(tools_zone_right_id())) + }); + if let Some(r) = left { + return Some((r, false)); + } + let r = right?; + // Read outside the data lock above: egui's context locks are not re-entrant. + let at_edge = at.x >= ctx.content_rect().right() - crate::toolbar::WIDTH && r.y_range().contains(at.y); + (r.contains(at) || at_edge).then_some((r, true)) } fn highlight(ctx: &egui::Context, zone: Rect) { @@ -138,6 +163,7 @@ pub fn track(app: &mut VectorcraftApp, ctx: &egui::Context) { let Some(m) = ctx.data(|d| d.get_temp::(move_id())) else { return }; if !gesture_allowed(ctx) { app.ui.toolbar_pos = m.original; + app.ui.toolbar_right = m.right; ctx.data_mut(|d| d.remove::(move_id())); if ctx.input(|i| i.key_pressed(Key::Escape)) { let frame = ctx.cumulative_frame_nr_for(ctx.viewport_id()); @@ -155,14 +181,15 @@ pub fn track(app: &mut VectorcraftApp, ctx: &egui::Context) { { app.ui.toolbar_pos = Some([p.x, p.y]); } - if let Some(zone) = zone { + if let Some((zone, _)) = zone { highlight(ctx, zone); } return; } ctx.data_mut(|d| d.remove::(move_id())); - if zone.is_some() { + if let Some((_, right)) = zone { app.ui.toolbar_pos = None; + app.ui.toolbar_right = right; } } @@ -191,9 +218,22 @@ pub(crate) fn command(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option Ok(app.ui.toolbar_right), + // `Start` and `End`, as panels take them, too. + Some(s) if s.eq_ignore_ascii_case("left") || s.eq_ignore_ascii_case("start") => Ok(false), + Some(s) if s.eq_ignore_ascii_case("right") || s.eq_ignore_ascii_case("end") => Ok(true), + Some(s) => Err(format!("side is left or right, not `{s}`")), + }; + Some(position(p).and_then(|at| { + let right = right?; app.ui.toolbar_pos = float.then(|| at.map_or(TOOLS_AT, |p| [p.x, p.y])); app.ui.toolbar |= float; - json!({ "panel": "tools", "floating": float, "pos": app.ui.toolbar_pos }) + if !float { + app.ui.toolbar_right = right; + } + let side = if app.ui.toolbar_right { "right" } else { "left" }; + Ok(json!({ "panel": "tools", "floating": float, "pos": app.ui.toolbar_pos, "side": side })) })) } diff --git a/crates/ui-egui/src/workspaces.rs b/crates/ui-egui/src/workspaces.rs index fa7f70d96..7e3c9acc4 100644 --- a/crates/ui-egui/src/workspaces.rs +++ b/crates/ui-egui/src/workspaces.rs @@ -61,6 +61,9 @@ pub struct Workspace { /// The docked Tools panel sits beside the canvas, inside any left-side panels (built-in /// workspaces and workspaces saved without it: at the window's left edge). pub tools_beside_canvas: bool, + /// The docked Tools panel stands on the right, left of the panels (built-in workspaces and + /// workspaces saved without it: on the left). + pub toolbar_right: bool, /// Main dock column width in screen points while `docking` is none (#1753). #[serde(default, skip_serializing_if = "Option::is_none")] pub dock_width: Option, @@ -203,6 +206,7 @@ pub fn capture(ui: &UiState, name: &str) -> Workspace { docking_collapsed: Default::default(), toolbar_pos: ui.toolbar_pos, tools_beside_canvas: ui.tools_beside_canvas, + toolbar_right: ui.toolbar_right, dock_width: ui.dock_width, toolbars: ui.custom_toolbars.clone(), } @@ -231,6 +235,7 @@ pub fn apply(ui: &mut UiState, w: &Workspace) { ui.docking_hidden_groups = w.docking_hidden_groups.clone(); ui.toolbar_pos = w.toolbar_pos; ui.tools_beside_canvas = w.tools_beside_canvas; + ui.toolbar_right = w.toolbar_right; ui.dock_width = w.dock_width; crate::state::sanitize_toolbar_pos(&mut ui.toolbar_pos); ui.custom_toolbars = w.toolbars.clone();