diff --git a/CHANGELOG.md b/CHANGELOG.md index d08446a..a84e35d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -475,6 +475,16 @@ because it turns other people's test suites red. ### Fixed +- **The window uses far less memory, and rebuilding a screen no longer adds + to it.** Every + quiet line on a screen - a subtitle, a caption, the count of bytes beside a + size, the line a folded section keeps, the message under a field - parsed + its own copy of the fonts, and parsed another each time the screen was + rebuilt and the line said something new. After visiting the four tabs the + window held about 290 MB and it now holds about 120 MB, and rebuilding a + screen no longer adds to it. Nothing on the screen looks different. The open + list of formats still does this when you type into its filter, and is next. + - **The `Several batches` screen no longer slows down the longer it is used.** Every batch added, removed or copied, every format chosen and every press of `Start from a preset` made each box on the screen report a change diff --git a/internal/guard/leftedge_test.go b/internal/guard/leftedge_test.go index 0f70a00..a2f06db 100644 --- a/internal/guard/leftedge_test.go +++ b/internal/guard/leftedge_test.go @@ -138,7 +138,9 @@ func TestTheActionBarSpeaksOnTheSameEdgeAsTheForm(t *testing.T) { if status == nil { t.Fatal("the bar is not naming the destination at rest, so this guard read the wrong tree") } - at, found := absoluteOf(generate, status) + // Measured where its words are, which labelBox knows for a line drawn + // ink tight - the label itself stands one padding to the left of them. + at, found := labelBox(generate, status.Text) if !found { t.Fatal("the status line is not on the screen it was found in") } diff --git a/internal/guard/spacingscale_test.go b/internal/guard/spacingscale_test.go index 0eb52f1..2feec5f 100644 --- a/internal/guard/spacingscale_test.go +++ b/internal/guard/spacingscale_test.go @@ -239,17 +239,34 @@ func gapBelowField(t *testing.T, screen fyne.CanvasObject, above, below string) // // Found by the text on the label rather than by a position handed in, because // a guard given coordinates would be a copy of the layout it is checking. +// +// A sentence drawn ink tight (parts.inkTight) is measured by the room it was +// given, not by the label. Since 2026-09-23 the layout places the label one +// inner padding up and left and one larger on every side, so its padding falls +// outside the room and its words land on the room's edge - the label's own +// box is where its padding is, and the room is where the ink is, exactly +// where the label stood when a theme override took the padding off instead. func labelBox(screen fyne.CanvasObject, words string) (band, bool) { found := band{} ok := false + tight := map[fyne.CanvasObject]band{} atAbsolute(screen, func(o fyne.CanvasObject, at fyne.Position) { if ok { return } + if room, is := o.(*fyne.Container); is && len(room.Objects) == 1 { + if p := room.Objects[0].Position(); p.X < 0 && p.X == p.Y { + tight[room.Objects[0]] = band{X: at.X, Y: at.Y, Width: room.Size().Width, Height: room.Size().Height} + } + } shown, is := wordsOf(o) if !is || shown != words { return } + if room, drawnTight := tight[o]; drawnTight { + found, ok = room, true + return + } found, ok = band{X: at.X, Y: at.Y, Width: o.Size().Width, Height: o.Size().Height}, true }) return found, ok diff --git a/internal/guard/testdata/screens/about.xml b/internal/guard/testdata/screens/about.xml index 60dfad9..50012c6 100644 --- a/internal/guard/testdata/screens/about.xml +++ b/internal/guard/testdata/screens/about.xml @@ -33,26 +33,22 @@ - - - - - Testing Files Generator 0.3.0 - + + + + Testing Files Generator 0.3.0 - - + + - - - - - Generate test files, and know how the system under test should react to them. - + + + + Generate test files, and know how the system under test should react to them. - - + + @@ -63,41 +59,35 @@ • - - - - - Choose a preset, or fill in one batch on the first screen. - - - - + + + + Choose a preset, or fill in one batch on the first screen. + + + • - - - - - Press Generate. The files and a manifest land in the output folder. - - - - + + + + Press Generate. The files and a manifest land in the output folder. + + + • - - - - - Point your test at the manifest. For every file it says what the system under test should do with it - accept it, reject it - or sanitize it - or records the outcome as unspecified, where the right answer belongs to the application's own - policy. - - - - + + + + Point your test at the manifest. For every file it says what the system under test should do with it - accept it, reject it + or sanitize it - or records the outcome as unspecified, where the right answer belongs to the application's own + policy. + + + @@ -110,28 +100,26 @@ Licence - - - - - Testing Files Generator - Copyright (C) 2026 DonislawDev - - Released under the GNU General Public License, version 3. The full text is at - https://www.gnu.org/licenses/gpl-3.0.html, and in the LICENSE file if you have the source or the full release. - - There is no warranty, to the extent the law allows. - - The files you generate are yours. Generated files, recipes and manifests are output of this program and not derived - works of it, so this licence does not reach them. You can generate fixtures, commit them and ship them inside a closed - source product with no obligation of any kind. - - Code from other projects is compiled into this program. Their licences and copyright notices are in - THIRD-PARTY-NOTICES.md, which comes with the source and with the full release. - + + + + Testing Files Generator + Copyright (C) 2026 DonislawDev + + Released under the GNU General Public License, version 3. The full text is at + https://www.gnu.org/licenses/gpl-3.0.html, and in the LICENSE file if you have the source or the full release. + + There is no warranty, to the extent the law allows. + + The files you generate are yours. Generated files, recipes and manifests are output of this program and not derived + works of it, so this licence does not reach them. You can generate fixtures, commit them and ship them inside a closed + source product with no obligation of any kind. + + Code from other projects is compiled into this program. Their licences and copyright notices are in + THIRD-PARTY-NOTICES.md, which comes with the source and with the full release. - - + + @@ -142,15 +130,13 @@ Support - - - - - Opens the support page in your browser. The tool is free and stays free - this pays for the time that goes into it. - + + + + Opens the support page in your browser. The tool is free and stays free - this pays for the time that goes into it. - - + + @@ -158,15 +144,13 @@ Donate - - - - - https://donislawdev.com/support/ - + + + + https://donislawdev.com/support/ - - + + @@ -179,904 +163,718 @@ - - - - - Go runtime and standard library - - - - - - - - - BSD-3-Clause - - - - - - - - - Copyright 2009 The Go Authors - - - - + + + + Go runtime and standard library + + + + + + + BSD-3-Clause + + + + + + + Copyright 2009 The Go Authors + + + - - - - - fyne.io/fyne/v2 - - - - - - - - - BSD-3-Clause - - - - - - - - - (C) 2018 Fyne.io developers (see AUTHORS) - - - - + + + + fyne.io/fyne/v2 + + + + + + + BSD-3-Clause + + + + + + + (C) 2018 Fyne.io developers (see AUTHORS) + + + - - - - - fyne.io/systray - - - - - - - - - Apache-2.0 - - - - - - - - - 2014 Brave New Software Project, Inc. - - - - + + + + fyne.io/systray + + + + + + + Apache-2.0 + + + + + + + 2014 Brave New Software Project, Inc. + + + - - - - - github.com/BurntSushi/toml - - - - - - - - - MIT - - - - - - - - - (c) 2013 TOML authors - - - - + + + + github.com/BurntSushi/toml + + + + + + + MIT + + + + + + + (c) 2013 TOML authors + + + - - - - - github.com/FyshOS/fancyfs - - - - - - - - - BSD-3-Clause - - - - - - - - - (C) 2025 FyshOS developers (see AUTHORS) - - - - + + + + github.com/FyshOS/fancyfs + + + + + + + BSD-3-Clause + + + + + + + (C) 2025 FyshOS developers (see AUTHORS) + + + - - - - - github.com/anthonynsimon/bild - - - - - - - - - MIT - - - - - - - - - (c) 2021 Anthony Najjar Simon - - - - + + + + github.com/anthonynsimon/bild + + + + + + + MIT + + + + + + + (c) 2021 Anthony Najjar Simon + + + - - - - - github.com/clipperhouse/uax29/v2 - - - - - - - - - MIT - - - - - - - - - (c) 2020 Matt Sherman - - - - + + + + github.com/clipperhouse/uax29/v2 + + + + + + + MIT + + + + + + + (c) 2020 Matt Sherman + + + - - - - - github.com/fsnotify/fsnotify - - - - - - - - - BSD-3-Clause - - - - - - - - - Copyright 2012 The Go Authors - - - - + + + + github.com/fsnotify/fsnotify + + + + + + + BSD-3-Clause + + + + + + + Copyright 2012 The Go Authors + + + - - - - - github.com/fyne-io/image - - - - - - - - - BSD-3-Clause - - - - - - - - - (c) 2022, Fyne.io - - - - + + + + github.com/fyne-io/image + + + + + + + BSD-3-Clause + + + + + + + (c) 2022, Fyne.io + + + - - - - - github.com/fyne-io/oksvg - - - - - - - - - BSD-3-Clause - - - - - - - - - (c) 2018, Steven R Wiley - - - - + + + + github.com/fyne-io/oksvg + + + + + + + BSD-3-Clause + + + + + + + (c) 2018, Steven R Wiley + + + - - - - - github.com/gen2brain/gav1d - - - - - - - - - BSD-2-Clause - - - - - - - - - (c) 2018-2025 VideoLAN and dav1d authors, (c) 2016 Alliance - for Open Media - - - - + + + + github.com/gen2brain/gav1d + + + + + + + BSD-2-Clause + + + + + + + (c) 2018-2025 VideoLAN and dav1d authors, (c) 2016 Alliance + for Open Media + + + - - - - - github.com/gen2brain/jxl - - - - - - - - - BSD-3-Clause - - - - - - - - - (c) the JPEG XL Project Authors - - - - + + + + github.com/gen2brain/jxl + + + + + + + BSD-3-Clause + + + + + + + (c) the JPEG XL Project Authors + + + - - - - - github.com/go-gl/gl - - - - - - - - - MIT - - - - - - - - - (c) 2014 Eric Woroshow - - - - + + + + github.com/go-gl/gl + + + + + + + MIT + + + + + + + (c) 2014 Eric Woroshow + + + - - - - - github.com/go-gl/glfw/v3.4/glfw - - - - - - - - - BSD-3-Clause - - - - - - - - - (c) 2012 The glfw3-go Authors. All rights reserved. - - - - + + + + github.com/go-gl/glfw/v3.4/glfw + + + + + + + BSD-3-Clause + + + + + + + (c) 2012 The glfw3-go Authors. All rights reserved. + + + - - - - - github.com/go-text/render - - - - - - - - - BSD-3-Clause - - - - - - - - - 2021 The go-text authors - - - - + + + + github.com/go-text/render + + + + + + + BSD-3-Clause + + + + + + + 2021 The go-text authors + + + - - - - - github.com/go-text/typesetting - - - - - - - - - BSD-3-Clause - - - - - - - - - 2021 The go-text authors - - - - + + + + github.com/go-text/typesetting + + + + + + + BSD-3-Clause + + + + + + + 2021 The go-text authors + + + - - - - - github.com/goccy/go-yaml - - - - - - - - - MIT - - - - - - - - - (c) 2019 Masaaki Goshima - - - - + + + + github.com/goccy/go-yaml + + + + + + + MIT + + + + + + + (c) 2019 Masaaki Goshima + + + - - - - - github.com/godbus/dbus/v5 - - - - - - - - - BSD-2-Clause - - - - - - - - - (c) 2013, Georg Reinke (), Google - - - - + + + + github.com/godbus/dbus/v5 + + + + + + + BSD-2-Clause + + + + + + + (c) 2013, Georg Reinke (), Google + + + - - - - - github.com/jeandeaual/go-locale - - - - - - - - - MIT - - - - - - - - - (c) 2020 Alexis Jeandeau - - - - + + + + github.com/jeandeaual/go-locale + + + + + + + MIT + + + + + + + (c) 2020 Alexis Jeandeau + + + - - - - - github.com/jsummers/gobmp - - - - - - - - - MIT - - - - - - - - - (c) 2012-2015 Jason Summers - - - - + + + + github.com/jsummers/gobmp + + + + + + + MIT + + + + + + + (c) 2012-2015 Jason Summers + + + - - - - - github.com/mattn/go-runewidth - - - - - - - - - MIT - - - - - - - - - (c) 2016 Yasuhiro Matsumoto - - - - + + + + github.com/mattn/go-runewidth + + + + + + + MIT + + + + + + + (c) 2016 Yasuhiro Matsumoto + + + - - - - - github.com/nfnt/resize - - - - - - - - - ISC - - - - - - - - - (c) 2012, Jan Schlicht - - - - + + + + github.com/nfnt/resize + + + + + + + ISC + + + + + + + (c) 2012, Jan Schlicht + + + - - - - - github.com/nicksnyder/go-i18n/v2 - - - - - - - - - MIT - - - - - - - - - (c) 2014 Nick Snyder https://github.com/nicksnyder - - - - + + + + github.com/nicksnyder/go-i18n/v2 + + + + + + + MIT + + + + + + + (c) 2014 Nick Snyder https://github.com/nicksnyder + + + - - - - - github.com/rymdport/portal - - - - - - - - - Apache-2.0 - - - - - - - - - - - - - + + + + github.com/rymdport/portal + + + + + + + Apache-2.0 + + + + + + + + + + - - - - - github.com/srwiley/oksvg - - - - - - - - - BSD-3-Clause - - - - - - - - - (c) 2018, Steven R Wiley - - - - + + + + github.com/srwiley/oksvg + + + + + + + BSD-3-Clause + + + + + + + (c) 2018, Steven R Wiley + + + - - - - - github.com/srwiley/rasterx - - - - - - - - - BSD-3-Clause - - - - - - - - - (c) 2018, Steven R Wiley - - - - + + + + github.com/srwiley/rasterx + + + + + + + BSD-3-Clause + + + + + + + (c) 2018, Steven R Wiley + + + - - - - - github.com/yuin/goldmark - - - - - - - - - MIT - - - - - - - - - (c) 2019 Yusuke Inuzuka - - - - + + + + github.com/yuin/goldmark + + + + + + + MIT + + + + + + + (c) 2019 Yusuke Inuzuka + + + - - - - - golang.org/x/image - - - - - - - - - BSD-3-Clause - - - - - - - - - 2009 The Go Authors. - - - - + + + + golang.org/x/image + + + + + + + BSD-3-Clause + + + + + + + 2009 The Go Authors. + + + - - - - - golang.org/x/net - - - - - - - - - BSD-3-Clause - - - - - - - - - 2009 The Go Authors. - - - - + + + + golang.org/x/net + + + + + + + BSD-3-Clause + + + + + + + 2009 The Go Authors. + + + - - - - - golang.org/x/sys - - - - - - - - - BSD-3-Clause - - - - - - - - - 2009 The Go Authors. - - - - + + + + golang.org/x/sys + + + + + + + BSD-3-Clause + + + + + + + 2009 The Go Authors. + + + - - - - - golang.org/x/text - - - - - - - - - BSD-3-Clause - - - - - - - - - Copyright 2009 The Go Authors - - - - + + + + golang.org/x/text + + + + + + + BSD-3-Clause + + + + + + + Copyright 2009 The Go Authors + + + @@ -1091,237 +889,189 @@ - - - - - DejaVu Sans Mono for Powerline - - - - - - - - - Bitstream-Vera - - - - - - - - - Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. - DejaVu changes are in public domain - - - - + + + + DejaVu Sans Mono for Powerline + + + + + + + Bitstream-Vera + + + + + + + Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. + DejaVu changes are in public domain + + + - - - - - EmojiOne Color - - - - - - - - - MIT - - - - - - - - - Copyright 2016 Adobe Systems Incorporated - - - - + + + + EmojiOne Color + + + + + + + MIT + + + + + + + Copyright 2016 Adobe Systems Incorporated + + + - - - - - Fyne icon set - - - - - - - - - BSD-3-Clause - - - - - - - - - (C) 2018 Fyne.io developers (see AUTHORS) - - - - + + + + Fyne icon set + + + + + + + BSD-3-Clause + + + + + + + (C) 2018 Fyne.io developers (see AUTHORS) + + + - - - - - Fyne shaders - - - - - - - - - BSD-3-Clause - - - - - - - - - (C) 2018 Fyne.io developers (see AUTHORS) - - - - + + + + Fyne shaders + + + + + + + BSD-3-Clause + + + + + + + (C) 2018 Fyne.io developers (see AUTHORS) + + + - - - - - Fyne translations - - - - - - - - - BSD-3-Clause - - - - - - - - - (C) 2018 Fyne.io developers (see AUTHORS) - - - - + + + + Fyne translations + + + + + + + BSD-3-Clause + + + + + + + (C) 2018 Fyne.io developers (see AUTHORS) + + + - - - - - Inter - - - - - - - - - OFL-1.1 - - - - - - - - - Copyright 2016 The Inter Project Authors - - - - + + + + Inter + + + + + + + OFL-1.1 + + + + + + + Copyright 2016 The Inter Project Authors + + + - - - - - Inter Symbols - - - - - - - - - OFL-1.1 - - - - - - - - - (c) 2020 The Inter Project Authors - - - - + + + + Inter Symbols + + + + + + + OFL-1.1 + + + + + + + (c) 2020 The Inter Project Authors + + + - - - - - Noto Sans - - - - - - - - - OFL-1.1 - - - - - - - - - Copyright 2015 Google Inc. All Rights Reserved. - - - - + + + + Noto Sans + + + + + + + OFL-1.1 + + + + + + + Copyright 2015 Google Inc. All Rights Reserved. + + + @@ -1336,36 +1086,30 @@ - - - - - Mesa 3D, llvmpipe software - renderer 26.2.0 - - - - - - - - - MIT AND Apache-2.0 WITH - LLVM-exception AND BSL-1.0 - - - - - - - - - Copyright (C) 1999-2007 Brian Paul, - Copyright (C) 2008 VMware, Inc. - - - - + + + + Mesa 3D, llvmpipe software + renderer 26.2.0 + + + + + + + MIT AND Apache-2.0 WITH + LLVM-exception AND BSL-1.0 + + + + + + + Copyright (C) 1999-2007 Brian Paul, + Copyright (C) 2008 VMware, Inc. + + + diff --git a/internal/guard/testdata/screens/catalogue.xml b/internal/guard/testdata/screens/catalogue.xml index 5450baf..38fc683 100644 --- a/internal/guard/testdata/screens/catalogue.xml +++ b/internal/guard/testdata/screens/catalogue.xml @@ -4,21 +4,17 @@ - - - - - Catalogue - + + + + Catalogue - - - + + + - - - Every part of the window, in every state it has. - + + Every part of the window, in every state it has. @@ -31,12 +27,10 @@ Button - + - - - primary at rest - + + primary at rest @@ -49,12 +43,10 @@ - + - - - primary under the pointer - + + primary under the pointer @@ -67,12 +59,10 @@ - + - - - primary pressed - + + primary pressed @@ -85,12 +75,10 @@ - + - - - primary holding the keyboard - + + primary holding the keyboard @@ -103,12 +91,10 @@ - + - - - secondary at rest - + + secondary at rest @@ -121,12 +107,10 @@ - + - - - secondary under the pointer - + + secondary under the pointer @@ -139,12 +123,10 @@ - + - - - secondary pressed - + + secondary pressed @@ -157,12 +139,10 @@ - + - - - secondary holding the keyboard - + + secondary holding the keyboard @@ -175,12 +155,10 @@ - + - - - secondary disabled - + + secondary disabled @@ -193,12 +171,10 @@ - + - - - quiet at rest - + + quiet at rest @@ -211,12 +187,10 @@ - + - - - quiet under the pointer - + + quiet under the pointer @@ -229,12 +203,10 @@ - + - - - quiet pressed - + + quiet pressed @@ -247,12 +219,10 @@ - + - - - quiet holding the keyboard - + + quiet holding the keyboard @@ -265,12 +235,10 @@ - + - - - quiet disabled - + + quiet disabled @@ -283,12 +251,10 @@ - + - - - long text - + + long text @@ -301,12 +267,10 @@ - + - - - glyph at rest - + + glyph at rest @@ -319,12 +283,10 @@ - + - - - glyph under the pointer - + + glyph under the pointer @@ -337,12 +299,10 @@ - + - - - glyph holding the keyboard - + + glyph holding the keyboard @@ -355,12 +315,10 @@ - + - - - glyph disabled - + + glyph disabled @@ -383,12 +341,10 @@ Chooser - + - - - at rest - + + at rest @@ -408,12 +364,10 @@ - + - - - chosen - + + chosen @@ -433,12 +387,10 @@ - + - - - holding the keyboard - + + holding the keyboard @@ -461,12 +413,10 @@ - + - - - refused - + + refused @@ -489,12 +439,10 @@ - + - - - disabled - + + disabled @@ -514,12 +462,10 @@ - + - - - long value - + + long value @@ -539,12 +485,10 @@ - + - - - every format, showing the kind of its value - + + every format, showing the kind of its value @@ -575,12 +519,10 @@ Entry - + - - - empty, with its hint - + + empty, with its hint @@ -600,12 +542,10 @@ - + - - - typed - + + typed @@ -622,12 +562,10 @@ - + - - - holding the keyboard - + + holding the keyboard @@ -645,12 +583,10 @@ - + - - - disabled - + + disabled @@ -667,12 +603,10 @@ - + - - - long text - + + long text @@ -699,12 +633,10 @@ Toggle - + - - - off - + + off @@ -717,12 +649,10 @@ - + - - - on - + + on @@ -736,12 +666,10 @@ - + - - - under the pointer - + + under the pointer @@ -754,12 +682,10 @@ - + - - - holding the keyboard - + + holding the keyboard @@ -773,12 +699,10 @@ - + - - - disabled - + + disabled @@ -801,12 +725,10 @@ Segments - + - - - first chosen - + + first chosen @@ -825,12 +747,10 @@ - + - - - middle chosen - + + middle chosen @@ -848,12 +768,10 @@ - + - - - holding the keyboard - + + holding the keyboard @@ -872,12 +790,10 @@ - + - - - the last one under the pointer - + + the last one under the pointer @@ -896,12 +812,10 @@ - + - - - frozen, middle chosen - + + frozen, middle chosen @@ -919,12 +833,10 @@ - + - - - long words - + + long words @@ -953,12 +865,10 @@ OpenList - + - - - a few values, one chosen - + + a few values, one chosen @@ -1011,12 +921,10 @@ - + - - - nothing chosen yet - + + nothing chosen yet @@ -1068,12 +976,10 @@ - + - - - more values than a short window shows at once - + + more values than a short window shows at once @@ -1151,12 +1057,10 @@ - + - - - every value with the kind of thing it is - + + every value with the kind of thing it is @@ -1302,12 +1206,10 @@ - + - - - a long value - + + a long value @@ -1351,12 +1253,10 @@ - + - - - every format, under the heading of its kind, with a box to filter - + + every format, under the heading of its kind, with a box to filter @@ -1514,12 +1414,10 @@ - + - - - typed into, with the letters that matched in bold - + + typed into, with the letters that matched in bold @@ -1688,12 +1586,10 @@ - + - - - typed into, with nothing left - + + typed into, with nothing left @@ -1749,12 +1645,10 @@ Tabs - + - - - the strip, first word chosen - + + the strip, first word chosen @@ -1783,12 +1677,10 @@ - + - - - a word under the pointer - + + a word under the pointer @@ -1817,12 +1709,10 @@ - + - - - a word holding the keyboard - + + a word holding the keyboard @@ -1851,12 +1741,10 @@ - + - - - the strip with its screens under it - + + the strip with its screens under it @@ -1889,24 +1777,20 @@ - - - - - the first screen - + + + + the first screen - - + + - + - - - long words - + + long words @@ -1935,12 +1819,10 @@ Fields - + - - - a row - + + a row @@ -1969,12 +1851,10 @@ - + - - - a row that has to be filled in - + + a row that has to be filled in @@ -2006,12 +1886,10 @@ - + - - - a row the run refused - + + a row the run refused @@ -2038,25 +1916,21 @@ - - - - - a size of 3 B is below the smallest png, which is 73 B - + + + + a size of 3 B is below the smallest png, which is 73 B - - + + - + - - - a row frozen while a run goes - + + a row frozen while a run goes @@ -2085,12 +1959,10 @@ - + - - - a box to tick with its name beside it - + + a box to tick with its name beside it @@ -2113,12 +1985,10 @@ - + - - - a box to tick beside a named field, level with its box - + + a box to tick beside a named field, level with its box @@ -2169,12 +2039,10 @@ - + - - - a named control with no setting behind it - + + a named control with no setting behind it @@ -2198,12 +2066,10 @@ - + - - - a table: the names once over the columns, cells under them - + + a table: the names once over the columns, cells under them @@ -2313,26 +2179,22 @@ - + - - - a row of arbitrary cells - + + a row of arbitrary cells - - - - - Anything - + + + + Anything - - + + @@ -2356,12 +2218,10 @@ - + - - - a long name - + + a long name @@ -2401,12 +2261,10 @@ PropertyField - + - - - a number with a range - + + a number with a range @@ -2449,12 +2307,10 @@ - + - - - a choice from a closed set - + + a choice from a closed set @@ -2493,12 +2349,10 @@ - + - - - a yes or no - + + a yes or no @@ -2532,12 +2386,10 @@ - + - - - a size - + + a size @@ -2572,12 +2424,10 @@ - + - - - - + + @@ -2589,12 +2439,10 @@ - + - - - free text - + + free text @@ -2647,12 +2495,10 @@ ByteCount - + - - - a size counted out - + + a size counted out @@ -2677,12 +2523,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -2690,12 +2534,10 @@ - + - - - nothing to count yet - + + nothing to count yet @@ -2723,12 +2565,10 @@ - + - - - - + + @@ -2736,12 +2576,10 @@ - + - - - a large size - + + a large size @@ -2766,12 +2604,10 @@ - + - - - 2 147 483 648 B - + + 2 147 483 648 B @@ -2789,12 +2625,10 @@ Tips - + - - - the button beside a name - + + the button beside a name @@ -2835,12 +2669,10 @@ - + - - - the button under the pointer - + + the button under the pointer @@ -2883,16 +2715,14 @@ - - - - - 10mb The exact size every file will have, to the byte. - Units count in 1024s, so 10mb is 10 485 760 B. - + + + + 10mb The exact size every file will have, to the byte. + Units count in 1024s, so 10mb is 10 485 760 B. - - + + @@ -2909,81 +2739,67 @@ ErrorArea - + - - - silent - + + silent - + - - - one line - + + one line - - - - - size 3 B is below the smallest png, which is 73 B - + + + + size 3 B is below the smallest png, which is 73 B - - + + - + - - - a long message - + + a long message - - - - - Write a label inside each generated file, including the ones that are far too small to hold it. Write a label inside each - generated file, including the ones that are far too small to hold it - + + + + Write a label inside each generated file, including the ones that are far too small to hold it. Write a label inside each + generated file, including the ones that are far too small to hold it - - + + - + - - - offering the fix it asks for - + + offering the fix it asks for - - - - - AVIF cannot be smaller than 311 B. Requested: 1 B - + + + + AVIF cannot be smaller than 311 B. Requested: 1 B - - + + @@ -3004,12 +2820,10 @@ Progress - + - - - nothing done yet - + + nothing done yet @@ -3019,12 +2833,10 @@ - + - - - half done - + + half done @@ -3034,12 +2846,10 @@ - + - - - done - + + done @@ -3059,12 +2869,10 @@ Folding - + - - - open - + + open @@ -3085,10 +2893,8 @@ Notes for the manifest - - - - + + @@ -3097,27 +2903,23 @@ - - - - - inside the fold - + + + + inside the fold - - + + - + - - - closed - + + closed @@ -3138,10 +2940,8 @@ Notes for the manifest - - - - + + @@ -3154,12 +2954,10 @@ - + - - - closed, saying what it holds - + + closed, saying what it holds @@ -3180,15 +2978,15 @@ Settings for png - - - - - width 800, height 600 + + + + + width 800, height 600 - - - + + + @@ -3201,12 +2999,10 @@ - + - - - inner, open - + + inner, open @@ -3231,10 +3027,8 @@ Advanced - - - - + + @@ -3243,15 +3037,13 @@ - - - - - inside the inner fold - + + + + inside the inner fold - - + + @@ -3259,12 +3051,10 @@ - + - - - inner, closed - + + inner, closed @@ -3289,10 +3079,8 @@ Advanced - - - - + + @@ -3306,12 +3094,10 @@ - + - - - inner, a damage's settings - + + inner, a damage's settings @@ -3336,10 +3122,8 @@ Settings for zero-head - - - - + + @@ -3348,15 +3132,13 @@ - - - - - inside the inner fold - + + + + inside the inner fold - - + + @@ -3364,12 +3146,10 @@ - + - - - inner, notes for the manifest - + + inner, notes for the manifest @@ -3394,10 +3174,8 @@ Notes for the manifest - - - - + + @@ -3406,15 +3184,13 @@ - - - - - inside the inner fold - + + + + inside the inner fold - - + + @@ -3422,12 +3198,10 @@ - + - - - a long title - + + a long title @@ -3448,10 +3222,8 @@ Write a label inside each generated file, including the ones that are far too small to hold it - - - - + + @@ -3460,27 +3232,23 @@ - - - - - inside the fold - + + + + inside the fold - - + + - + - - - the head under the pointer - + + the head under the pointer @@ -3501,10 +3269,8 @@ Notes for the manifest - - - - + + @@ -3513,27 +3279,23 @@ - - - - - inside the fold - + + + + inside the fold - - + + - + - - - the head holding the keyboard - + + the head holding the keyboard @@ -3554,10 +3316,8 @@ Notes for the manifest - - - - + + @@ -3566,27 +3326,23 @@ - - - - - inside the fold - + + + + inside the fold - - + + - + - - - shut, the head under the pointer - + + shut, the head under the pointer @@ -3607,15 +3363,15 @@ Settings for png - - - - - width 800, height 600 + + + + + width 800, height 600 - - - + + + @@ -3638,406 +3394,330 @@ Title - + - - - the title of a screen - + + the title of a screen - - - - - Single batch - + + + + Single batch - - + + - + - - - the sentence under a title - + + the sentence under a title - + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. - + - - - a title with its sentence - + + a title with its sentence - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. - + - - - the name of a field - + + the name of a field Output directory - + - - - the name of a block inside a section - + + the name of a block inside a section - - - - - Typically finds - + + + + Typically finds - - + + - + - - - a paragraph - + + a paragraph - - - - - Every file has exactly the size you ask for, to the byte, or the run refuses before writing anything. - + + + + Every file has exactly the size you ask for, to the byte, or the run refuses before writing anything. - - + + - + - - - a note that has to stay visible - + + a note that has to stay visible - + - - - The limit of 100 000 files is this tool's, not the disk's. - + + The limit of 100 000 files is this tool's, not the disk's. - + - - - a list of short statements - + + a list of short statements • - - - - - Upload validators - + + + + Upload validators - - + + • - - - - - Size limits - + + + + Size limits - - + + • - - - - - Archive handling - + + + + Archive handling - - + + - + - - - a list whose items do not fit on one line - + + a list whose items do not fit on one line • - - - - - One line - + + + + One line - - + + • - - - - - Write a label inside each generated file, including the ones that are far too small to hold it Write a label inside each - generated file, including the ones that are far too small to hold it - + + + + Write a label inside each generated file, including the ones that are far too small to hold it Write a label inside each + generated file, including the ones that are far too small to hold it - - + + - + - - - a caption, the smallest rank - + + a caption, the smallest rank - + - - - 10 485 760 B - + + 10 485 760 B - + - - - a table of three columns, the last one wrapping - + + a table of three columns, the last one wrapping - - - - - fyne.io/fyne/v2 - + + + + fyne.io/fyne/v2 - - - - - - - BSD-3-Clause - + + + + + + BSD-3-Clause - - - - - - - (C) 2018 Fyne.io developers (see - AUTHORS) - + + + + + + (C) 2018 Fyne.io developers (see + AUTHORS) - - + + - - - - - Mesa 3D, llvmpipe software - renderer 26.2.0 - + + + + Mesa 3D, llvmpipe software + renderer 26.2.0 - - - - - - - MIT AND Apache-2.0 WITH - LLVM-exception AND BSL-1.0 - + + + + + + MIT AND Apache-2.0 WITH + LLVM-exception AND BSL-1.0 - - - - - - - Copyright (C) 1999-2007 Brian Paul, - Copyright (C) 2008 VMware, Inc. - + + + + + + Copyright (C) 1999-2007 Brian Paul, + Copyright (C) 2008 VMware, Inc. - - + + - - - - - golang.org/x/text - + + + + golang.org/x/text - - - - - - - BSD-3-Clause - + + + + + + BSD-3-Clause - - - - - - - Write a label inside each generated - file, including the ones that are far too - small to hold it - + + + + + + Write a label inside each generated + file, including the ones that are far too + small to hold it - - + + - + - - - a long line at every rank - + + a long line at every rank - - - - - Write a label inside each generated file, including the ones that are far too sma… - + + + + Write a label inside each generated file, including the ones that are far too sma… - - + + Write a label inside each generated file, including the ones that are far too small to hold it - - - - - Write a label inside each generated file, including the ones that are far too small to hold it - + + + + Write a label inside each generated file, including the ones that are far too small to hold it - - - - - - - Write a label inside each generated file, including the ones that are far too small to hold it - + + + + + + Write a label inside each generated file, including the ones that are far too small to hold it - - - + + + - - - Write a label inside each generated file, including the ones that are far too small to hold it - + + Write a label inside each generated file, including the ones that are far too small to hold it @@ -4054,12 +3734,10 @@ Section - + - - - a section of two rows - + + a section of two rows @@ -4123,12 +3801,10 @@ - + - - - a section with a line across it - + + a section with a line across it @@ -4194,12 +3870,10 @@ - + - - - the bar a run starts from - + + the bar a run starts from @@ -4239,12 +3913,10 @@ - + - - - fields in columns, each as wide as its value needs - + + fields in columns, each as wide as its value needs @@ -4379,12 +4051,10 @@ - + - - - a row with a refusal under it - + + a row with a refusal under it @@ -4420,15 +4090,13 @@ - - - - - size 3 B is below the smallest png, which is 73 B - + + + + size 3 B is below the smallest png, which is 73 B - - + + @@ -4457,16 +4125,14 @@ - - - - - Write a label inside each generated file, including the ones that are far too small to - hold it - + + + + Write a label inside each generated file, including the ones that are far too small to + hold it - - + + @@ -4501,12 +4167,10 @@ - + - - - a section with a long title - + + a section with a long title @@ -4580,12 +4244,10 @@ Swatch - + - - - a surface near the bottom of the ladder - + + a surface near the bottom of the ladder @@ -4594,12 +4256,10 @@ - + - - - a surface near the top of it - + + a surface near the top of it @@ -4608,12 +4268,10 @@ - + - - - a colour that carries meaning - + + a colour that carries meaning @@ -4622,12 +4280,10 @@ - + - - - an ink, which is nearly white - + + an ink, which is nearly white @@ -4636,12 +4292,10 @@ - + - - - something the toolkit blends, laid over a panel first - + + something the toolkit blends, laid over a panel first @@ -4659,42 +4313,34 @@ Palette, as this window draws it - + - - - Every colour the window paints with, measured against what it is drawn on. - + + Every colour the window paints with, measured against what it is drawn on. - - - - - The ladder of surfaces - + + + + The ladder of surfaces - - + + - + - - - background - the page the window stands on - + + background - the page the window stands on - + - - - #1E1E20 - + + #1E1E20 @@ -4703,21 +4349,17 @@ - + - - - panel - the surface a section is drawn on - + + panel - the surface a section is drawn on - + - - - #2B2B2F - 17.7 L*, +6.3 from the page - + + #2B2B2F - 17.7 L*, +6.3 from the page @@ -4726,21 +4368,17 @@ - + - - - inputBackground - the fill of a box to type in - + + inputBackground - the fill of a box to type in - + - - - #39393F - 24.2 L*, +6.5 from the panel - + + #39393F - 24.2 L*, +6.5 from the panel @@ -4749,21 +4387,17 @@ - + - - - button - the face of a button that is not the main one - + + button - the face of a button that is not the main one - + - - - #48484E - 30.8 L*, +6.6 from a box to type in - + + #48484E - 30.8 L*, +6.6 from a box to type in @@ -4772,21 +4406,17 @@ - + - - - separator - a line that separates and says nothing else - + + separator - a line that separates and says nothing else - + - - - #48484E - 30.8 L*, +13.1 from the panel - + + #48484E - 30.8 L*, +13.1 from the panel @@ -4795,21 +4425,17 @@ - + - - - menuBackground - what an open list floats on - + + menuBackground - what an open list floats on - + - - - #57575F - 37.2 L*, +13.1 from a box to type in - + + #57575F - 37.2 L*, +13.1 from a box to type in @@ -4818,53 +4444,43 @@ - + - - - inputBorder - the edge that says where the typing goes - + + inputBorder - the edge that says where the typing goes - + - - - #65656D - 43.0 L*, +18.9 from its own fill - + + #65656D - 43.0 L*, +18.9 from its own fill - - - - - The inks - + + + + The inks - - + + - + - - - foreground - a value, and everything read at rest - + + foreground - a value, and everything read at rest - + - - - #E6E6E8 - 5.74:1 on an open list - + + #E6E6E8 - 5.74:1 on an open list @@ -4873,21 +4489,17 @@ - + - - - label - the name of a field, a step quieter than its value - + + label - the name of a field, a step quieter than its value - + - - - #D3D3D7 - 9.45:1 on a panel - + + #D3D3D7 - 9.45:1 on a panel @@ -4896,21 +4508,17 @@ - + - - - disabled - a value in a box switched off for the length of a run - + + disabled - a value in a box switched off for the length of a run - + - - - #C7C7CC - 6.81:1 on a box to type in - + + #C7C7CC - 6.81:1 on a box to type in @@ -4919,53 +4527,43 @@ - + - - - placeholder - a hint in a box nobody has typed in - + + placeholder - a hint in a box nobody has typed in - + - - - #A2A2A9 - 4.52:1 on a box to type in - + + #A2A2A9 - 4.52:1 on a box to type in - - - - - What carries meaning - + + + + What carries meaning - - + + - + - - - primary - the action a screen is for, and the line round a focused control - + + primary - the action a screen is for, and the line round a focused control - + - - - #5AB3F2 - 7.26:1 on the page - + + #5AB3F2 - 7.26:1 on the page @@ -4974,21 +4572,17 @@ - + - - - hyperlink - a link, the same blue as the action - + + hyperlink - a link, the same blue as the action - + - - - #5AB3F2 - 7.26:1 on the page - + + #5AB3F2 - 7.26:1 on the page @@ -4997,21 +4591,17 @@ - + - - - error - a refusal, and a file that failed - + + error - a refusal, and a file that failed - + - - - #F48F8D - 7.26:1 on the page - + + #F48F8D - 7.26:1 on the page @@ -5020,21 +4610,17 @@ - + - - - success - a run that wrote everything it promised - + + success - a run that wrote everything it promised - + - - - #42C260 - 7.23:1 on the page - + + #42C260 - 7.23:1 on the page @@ -5043,21 +4629,17 @@ - + - - - warning - a run that wrote files and skipped some - + + warning - a run that wrote files and skipped some - + - - - #DAA131 - 7.23:1 on the page - + + #DAA131 - 7.23:1 on the page @@ -5066,53 +4648,43 @@ - + - - - selection - the row or the segment somebody chose - + + selection - the row or the segment somebody chose - + - - - #224B69 - 30.4 L*, +19.0 from the page - + + #224B69 - 30.4 L*, +19.0 from the page - - - - - What the pointer, a press and the keyboard do - + + + + What the pointer, a press and the keyboard do - - + + - + - - - hover - what the pointer does to a dark face - + + hover - what the pointer does to a dark face - + - - - #FFFFFF at 0x22 - over the page it comes to #3C3C3D, 25.4 L*, a move of +14.0 - + + #FFFFFF at 0x22 - over the page it comes to #3C3C3D, 25.4 L*, a move of +14.0 @@ -5121,21 +4693,17 @@ - + - - - pressed - what a press does to a dark face - + + pressed - what a press does to a dark face - + - - - #FFFFFF at 0x40 - over a button's face it comes to #76767A, 49.7 L*, a move of +19.0 - + + #FFFFFF at 0x40 - over a button's face it comes to #76767A, 49.7 L*, a move of +19.0 @@ -5144,21 +4712,17 @@ - + - - - lift - what the pointer does to the filled main button - + + lift - what the pointer does to the filled main button - + - - - #FFFFFF at 0x66 - over the main button it comes to #9CD2F8, 81.6 L*, a move of +11.6 - + + #FFFFFF at 0x66 - over the main button it comes to #9CD2F8, 81.6 L*, a move of +11.6 @@ -5167,21 +4731,17 @@ - + - - - shade - what a press does to the filled main button - + + shade - what a press does to the filled main button - + - - - #000000 at 0x33 - over the main button it comes to #488FC2, 57.0 L*, a move of -13.0 - + + #000000 at 0x33 - over the main button it comes to #488FC2, 57.0 L*, a move of -13.0 @@ -5190,21 +4750,17 @@ - + - - - focus - the wash the toolkit lays over a control the keyboard is in - + + focus - the wash the toolkit lays over a control the keyboard is in - + - - - #00A5F0 at 0x66 - over a box to type in it comes to #226486, 39.9 L*, a move of +15.8 - + + #00A5F0 at 0x66 - over a box to type in it comes to #226486, 39.9 L*, a move of +15.8 @@ -5213,21 +4769,17 @@ - + - - - tipshade - the shade an explanation casts on the form under it - + + tipshade - the shade an explanation casts on the form under it - + - - - #000000 at 0x66 - over a panel it comes to #19191C, 9.3 L*, a move of -8.4 - + + #000000 at 0x66 - over a panel it comes to #19191C, 9.3 L*, a move of -8.4 @@ -5236,53 +4788,43 @@ - + - - - shadow - what a popup casts - nothing here, on purpose - + + shadow - what a popup casts - nothing here, on purpose - + - - - nothing - drawn transparent on purpose - + + nothing - drawn transparent on purpose - - - - - What is written on a filled face - + + + + What is written on a filled face - - + + - + - - - foregroundOnPrimary - the word on the main button - + + foregroundOnPrimary - the word on the main button - + - - - #1A1A1A - 7.60:1 on the main button - + + #1A1A1A - 7.60:1 on the main button @@ -5291,21 +4833,17 @@ - + - - - foregroundOnError - what is written on a filled red - + + foregroundOnError - what is written on a filled red - + - - - #1A1A1A - 7.59:1 on a filled red - + + #1A1A1A - 7.59:1 on a filled red @@ -5314,21 +4852,17 @@ - + - - - foregroundOnSuccess - what is written on a filled green - + + foregroundOnSuccess - what is written on a filled green - + - - - #1A1A1A - 7.56:1 on a filled green - + + #1A1A1A - 7.56:1 on a filled green @@ -5337,21 +4871,17 @@ - + - - - foregroundOnWarning - what is written on a filled amber - + + foregroundOnWarning - what is written on a filled amber - + - - - #1A1A1A - 7.56:1 on a filled amber - + + #1A1A1A - 7.56:1 on a filled amber @@ -5367,42 +4897,34 @@ Palette, light - computed and not installed - + - - - Worked out and guarded to the same thresholds. The window does not use it: this program has one look. - + + Worked out and guarded to the same thresholds. The window does not use it: this program has one look. - - - - - The ladder of surfaces - + + + + The ladder of surfaces - - + + - + - - - background - the page the window stands on - + + background - the page the window stands on - + - - - #FFFFFF - + + #FFFFFF @@ -5411,21 +4933,17 @@ - + - - - panel - the surface a section is drawn on - + + panel - the surface a section is drawn on - + - - - #EEEEEF - 94.1 L*, -5.9 from the page - + + #EEEEEF - 94.1 L*, -5.9 from the page @@ -5434,21 +4952,17 @@ - + - - - inputBackground - the fill of a box to type in - + + inputBackground - the fill of a box to type in - + - - - #DCDCE0 - 87.9 L*, -6.3 from the panel - + + #DCDCE0 - 87.9 L*, -6.3 from the panel @@ -5457,21 +4971,17 @@ - + - - - button - the face of a button that is not the main one - + + button - the face of a button that is not the main one - + - - - #CCCBD1 - 81.9 L*, -5.9 from a box to type in - + + #CCCBD1 - 81.9 L*, -5.9 from a box to type in @@ -5480,21 +4990,17 @@ - + - - - separator - a line that separates and says nothing else - + + separator - a line that separates and says nothing else - + - - - #CCCBD1 - 81.9 L*, -12.2 from the panel - + + #CCCBD1 - 81.9 L*, -12.2 from the panel @@ -5503,21 +5009,17 @@ - + - - - menuBackground - what an open list floats on - + + menuBackground - what an open list floats on - + - - - #FFFFFF - 100.0 L*, +12.1 from a box to type in - + + #FFFFFF - 100.0 L*, +12.1 from a box to type in @@ -5526,53 +5028,43 @@ - + - - - inputBorder - the edge that says where the typing goes - + + inputBorder - the edge that says where the typing goes - + - - - #ABAAB2 - 69.9 L*, -18.0 from its own fill - + + #ABAAB2 - 69.9 L*, -18.0 from its own fill - - - - - The inks - + + + + The inks - - + + - + - - - foreground - a value, and everything read at rest - + + foreground - a value, and everything read at rest - + - - - #1A1A1C - 17.38:1 on an open list - + + #1A1A1C - 17.38:1 on an open list @@ -5581,21 +5073,17 @@ - + - - - label - the name of a field, a step quieter than its value - + + label - the name of a field, a step quieter than its value - + - - - #434349 - 8.47:1 on a panel - + + #434349 - 8.47:1 on a panel @@ -5604,21 +5092,17 @@ - + - - - disabled - a value in a box switched off for the length of a run - + + disabled - a value in a box switched off for the length of a run - + - - - #3D3D42 - 7.90:1 on a box to type in - + + #3D3D42 - 7.90:1 on a box to type in @@ -5627,53 +5111,43 @@ - + - - - placeholder - a hint in a box nobody has typed in - + + placeholder - a hint in a box nobody has typed in - + - - - #585860 - 5.15:1 on a box to type in - + + #585860 - 5.15:1 on a box to type in - - - - - What carries meaning - + + + + What carries meaning - - + + - + - - - primary - the action a screen is for, and the line round a focused control - + + primary - the action a screen is for, and the line round a focused control - + - - - #286893 - 6.01:1 on the page - + + #286893 - 6.01:1 on the page @@ -5682,21 +5156,17 @@ - + - - - hyperlink - a link, the same blue as the action - + + hyperlink - a link, the same blue as the action - + - - - #286893 - 6.01:1 on the page - + + #286893 - 6.01:1 on the page @@ -5705,21 +5175,17 @@ - + - - - error - a refusal, and a file that failed - + + error - a refusal, and a file that failed - + - - - #BB293B - 6.01:1 on the page - + + #BB293B - 6.01:1 on the page @@ -5728,21 +5194,17 @@ - + - - - success - a run that wrote everything it promised - + + success - a run that wrote everything it promised - + - - - #237135 - 6.03:1 on the page - + + #237135 - 6.03:1 on the page @@ -5751,21 +5213,17 @@ - + - - - warning - a run that wrote files and skipped some - + + warning - a run that wrote files and skipped some - + - - - #805D18 - 6.01:1 on the page - + + #805D18 - 6.01:1 on the page @@ -5774,53 +5232,43 @@ - + - - - selection - the row or the segment somebody chose - + + selection - the row or the segment somebody chose - + - - - #C1E0FF - 87.9 L*, -12.1 from the page - + + #C1E0FF - 87.9 L*, -12.1 from the page - - - - - What the pointer, a press and the keyboard do - + + + + What the pointer, a press and the keyboard do - - + + - + - - - hover - what the pointer does to a dark face - + + hover - what the pointer does to a dark face - + - - - #000000 at 0x20 - over the page it comes to #DFDFDF, 88.8 L*, a move of -11.2 - + + #000000 at 0x20 - over the page it comes to #DFDFDF, 88.8 L*, a move of -11.2 @@ -5829,21 +5277,17 @@ - + - - - pressed - what a press does to a dark face - + + pressed - what a press does to a dark face - + - - - #000000 at 0x33 - over a button's face it comes to #A3A3A7, 67.0 L*, a move of -15.0 - + + #000000 at 0x33 - over a button's face it comes to #A3A3A7, 67.0 L*, a move of -15.0 @@ -5852,21 +5296,17 @@ - + - - - lift - what the pointer does to the filled main button - + + lift - what the pointer does to the filled main button - + - - - #FFFFFF at 0x66 - over the main button it comes to #7EA5BE, 65.6 L*, a move of +23.7 - + + #FFFFFF at 0x66 - over the main button it comes to #7EA5BE, 65.6 L*, a move of +23.7 @@ -5875,21 +5315,17 @@ - + - - - shade - what a press does to the filled main button - + + shade - what a press does to the filled main button - + - - - #000000 at 0x33 - over the main button it comes to #205376, 33.6 L*, a move of -8.3 - + + #000000 at 0x33 - over the main button it comes to #205376, 33.6 L*, a move of -8.3 @@ -5898,21 +5334,17 @@ - + - - - focus - the wash the toolkit lays over a control the keyboard is in - + + focus - the wash the toolkit lays over a control the keyboard is in - + - - - #007FBA at 0x66 - over a box to type in it comes to #84B7D1, 71.7 L*, a move of -16.1 - + + #007FBA at 0x66 - over a box to type in it comes to #84B7D1, 71.7 L*, a move of -16.1 @@ -5921,21 +5353,17 @@ - + - - - tipshade - the shade an explanation casts on the form under it - + + tipshade - the shade an explanation casts on the form under it - + - - - #000000 at 0x40 - over a panel it comes to #B2B2B3, 72.7 L*, a move of -21.4 - + + #000000 at 0x40 - over a panel it comes to #B2B2B3, 72.7 L*, a move of -21.4 @@ -5944,53 +5372,43 @@ - + - - - shadow - what a popup casts - nothing here, on purpose - + + shadow - what a popup casts - nothing here, on purpose - + - - - #000000 at 0x40 - + + #000000 at 0x40 - - - - - What is written on a filled face - + + + + What is written on a filled face - - + + - + - - - foregroundOnPrimary - the word on the main button - + + foregroundOnPrimary - the word on the main button - + - - - #FFFFFF - 6.01:1 on the main button - + + #FFFFFF - 6.01:1 on the main button @@ -5999,21 +5417,17 @@ - + - - - foregroundOnError - what is written on a filled red - + + foregroundOnError - what is written on a filled red - + - - - #FFFFFF - 6.01:1 on a filled red - + + #FFFFFF - 6.01:1 on a filled red @@ -6022,21 +5436,17 @@ - + - - - foregroundOnSuccess - what is written on a filled green - + + foregroundOnSuccess - what is written on a filled green - + - - - #FFFFFF - 6.03:1 on a filled green - + + #FFFFFF - 6.03:1 on a filled green @@ -6045,21 +5455,17 @@ - + - - - foregroundOnWarning - what is written on a filled amber - + + foregroundOnWarning - what is written on a filled amber - + - - - #FFFFFF - 6.01:1 on a filled amber - + + #FFFFFF - 6.01:1 on a filled amber @@ -6078,136 +5484,114 @@ • - - - - - Choice - a value: one row of an open list, read back by a guard - + + + + Choice - a value: one row of an open list, read back by a guard - - + + • - - - - - Detail - data: the longer explanation of a field and the sheet it opens on - + + + + Detail - data: the longer explanation of a field and the sheet it opens on - - + + • - - - - - Field - the model of one row of a form, drawn by Fields - + + + + Field - the model of one row of a form, drawn by Fields - - + + • - - - - - Built - a value: what building a field comes to, handed to the registry in one piece - + + + + Built - a value: what building a field comes to, handed to the registry in one piece - - + + • - - - - - Tab - data: one screen and the word that leads to it, drawn by Tabs - + + + + Tab - data: one screen and the word that leads to it, drawn by Tabs - - + + • - - - - - Look - an enum: which face a Button wears, every value drawn under Button - + + + + Look - an enum: which face a Button wears, every value drawn under Button - - + + • - - - - - PointerFocus - a piece inside a control, knowing what put the keyboard there - no picture of its own - + + + + PointerFocus - a piece inside a control, knowing what put the keyboard there - no picture of its own - - + + • - - - - - Returnable - an interface: a control the window can tell it is coming back to the front, nothing of its own to draw - + + + + Returnable - an interface: a control the window can tell it is coming back to the front, nothing of its own to draw - - + + • - - - - - Shortcuts - a keyboard map: nothing to draw, and saying so is the point of this row - + + + + Shortcuts - a keyboard map: nothing to draw, and saying so is the point of this row - - + + • - - - - - GroupKind - an enum: what a group of settings is about, every value drawn under Folding as the colour of its rail - + + + + GroupKind - an enum: what a group of settings is about, every value drawn under Folding as the colour of its rail - - + + • - - - - - NameTap - an invisible target over the name beside a box to tick, so pressing the name ticks the box - nothing of its - own to draw - + + + + NameTap - an invisible target over the name beside a box to tick, so pressing the name ticks the box - nothing of its + own to draw - - + + @@ -6223,207 +5607,173 @@ • - - - - - Column - stacks children at one gap of the scale - + + + + Column - stacks children at one gap of the scale - - + + • - - - - - Row - puts fields side by side - + + + + Row - puts fields side by side - - + + • - - - - - FieldColumn - the column a screen refills at run time, stacked like a section - + + + + FieldColumn - the column a screen refills at run time, stacked like a section - - + + • - - - - - Indented - the same left edge as the fields inside a panel - + + + + Indented - the same left edge as the fields inside a panel - - + + • - - - - - Sized - one width, given - + + + + Sized - one width, given - - + + • - - - - - Numeric - the width a number needs - + + + + Numeric - the width a number needs - - + + • - - - - - Text - the width a short piece of text needs - a name, a template, a file name - + + + + Text - the width a short piece of text needs - a name, a template, a file name - - + + • - - - - - Padded - one distance of the scale round its content - + + + + Padded - one distance of the scale round its content - - + + • - - - - - Stacked - panels one under another - + + + + Stacked - panels one under another - - + + • - - - - - Screen - the readable width round a head and its sections - + + + + Screen - the readable width round a head and its sections - - + + • - - - - - BesideFields - the room to the right of the column of names - + + + + BesideFields - the room to the right of the column of names - - + + • - - - - - WithRoomForARun - the room under a form for the bar to speak into - + + + + WithRoomForARun - the room under a form for the bar to speak into - - + + • - - - - - Flush - a label kept by a screen, on the edge every other word stands on - + + + + Flush - a label kept by a screen, on the edge every other word stands on - - + + • - - - - - Clear - a shape that takes room and draws nothing - + + + + Clear - a shape that takes room and draws nothing - - + + • - - - - - Grid - lays a section's fields in columns, each taking the columns its value needs - drawn under Section - + + + + Grid - lays a section's fields in columns, each taking the columns its value needs - drawn under Section - - + + • - - - - - Wide - marks something that takes a whole row of a Grid - + + + + Wide - marks something that takes a whole row of a Grid - - + + • - - - - - ButtonRow - buttons side by side, one gap of the scale apart and centred - drawn under Section - + + + + ButtonRow - buttons side by side, one gap of the scale apart and centred - drawn under Section - - + + diff --git a/internal/guard/testdata/screens/generate-chosen-by-key.xml b/internal/guard/testdata/screens/generate-chosen-by-key.xml index 53378a3..ea60d4f 100644 --- a/internal/guard/testdata/screens/generate-chosen-by-key.xml +++ b/internal/guard/testdata/screens/generate-chosen-by-key.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,12 +136,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -290,10 +282,8 @@ Settings for png - - - - + + @@ -329,10 +319,8 @@ Output - - - - + + @@ -462,15 +450,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · png · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · png · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-chosen.xml b/internal/guard/testdata/screens/generate-chosen.xml index 59cab24..778cc5f 100644 --- a/internal/guard/testdata/screens/generate-chosen.xml +++ b/internal/guard/testdata/screens/generate-chosen.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,12 +136,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -290,10 +282,8 @@ Settings for png - - - - + + @@ -329,10 +319,8 @@ Output - - - - + + @@ -462,15 +450,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · png · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · png · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-empty.xml b/internal/guard/testdata/screens/generate-empty.xml index db2047c..66eafad 100644 --- a/internal/guard/testdata/screens/generate-empty.xml +++ b/internal/guard/testdata/screens/generate-empty.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,12 +136,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -180,15 +172,13 @@ - - - - - target "files" asks for 0 files. Ask for at least one - + + + + target "files" asks for 0 files. Ask for at least one - - + + @@ -302,10 +292,8 @@ Settings for avif - - - - + + @@ -341,10 +329,8 @@ Output - - - - + + @@ -474,15 +460,13 @@ - - - - - 0 files · 0 B · avif · will go to /tfg/out - + + + + 0 files · 0 B · avif · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-focused.xml b/internal/guard/testdata/screens/generate-focused.xml index 04c979f..03f03a6 100644 --- a/internal/guard/testdata/screens/generate-focused.xml +++ b/internal/guard/testdata/screens/generate-focused.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -143,12 +137,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -291,10 +283,8 @@ Settings for avif - - - - + + @@ -330,10 +320,8 @@ Output - - - - + + @@ -463,15 +451,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-hovered.xml b/internal/guard/testdata/screens/generate-hovered.xml index 90c189a..cbcc47d 100644 --- a/internal/guard/testdata/screens/generate-hovered.xml +++ b/internal/guard/testdata/screens/generate-hovered.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,12 +136,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -290,10 +282,8 @@ Settings for avif - - - - + + @@ -329,10 +319,8 @@ Output - - - - + + @@ -462,15 +450,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - - + + @@ -497,17 +483,15 @@ - - - - - Exact size of every file. Units count in 1024s, so - 10mb is 10485760 bytes. A plain number is a count - of bytes. - + + + + Exact size of every file. Units count in 1024s, so + 10mb is 10485760 bytes. A plain number is a count + of bytes. - - + + diff --git a/internal/guard/testdata/screens/generate-menu-hovered.xml b/internal/guard/testdata/screens/generate-menu-hovered.xml index 6cc8440..d4d7039 100644 --- a/internal/guard/testdata/screens/generate-menu-hovered.xml +++ b/internal/guard/testdata/screens/generate-menu-hovered.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,12 +136,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -290,10 +282,8 @@ Settings for avif - - - - + + @@ -329,10 +319,8 @@ Output - - - - + + @@ -462,15 +450,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-menu-keyed.xml b/internal/guard/testdata/screens/generate-menu-keyed.xml index 200cfe0..ce19722 100644 --- a/internal/guard/testdata/screens/generate-menu-keyed.xml +++ b/internal/guard/testdata/screens/generate-menu-keyed.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,12 +136,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -290,10 +282,8 @@ Settings for avif - - - - + + @@ -329,10 +319,8 @@ Output - - - - + + @@ -462,15 +450,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-menu.xml b/internal/guard/testdata/screens/generate-menu.xml index 40fa0b6..4ba61bd 100644 --- a/internal/guard/testdata/screens/generate-menu.xml +++ b/internal/guard/testdata/screens/generate-menu.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,12 +136,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -290,10 +282,8 @@ Settings for avif - - - - + + @@ -329,10 +319,8 @@ Output - - - - + + @@ -462,15 +450,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-refused-both.xml b/internal/guard/testdata/screens/generate-refused-both.xml index a327525..a7483f7 100644 --- a/internal/guard/testdata/screens/generate-refused-both.xml +++ b/internal/guard/testdata/screens/generate-refused-both.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -143,26 +137,22 @@ - + - - - - + + - - - - - Size "abc" has no number: write something like 10mb or 1048576 - + + + + Size "abc" has no number: write something like 10mb or 1048576 - - + + @@ -191,16 +181,14 @@ - - - - - How many files is "many", which is not a whole number. - Write the digits out, such as 1 or 500 - + + + + How many files is "many", which is not a whole number. + Write the digits out, such as 1 or 500 - - + + @@ -314,10 +302,8 @@ Settings for avif - - - - + + @@ -353,10 +339,8 @@ Output - - - - + + @@ -486,15 +470,13 @@ - - - - - Files will go to /tfg/out - + + + + Files will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-refused-setting.xml b/internal/guard/testdata/screens/generate-refused-setting.xml index 696f034..ad0c6f2 100644 --- a/internal/guard/testdata/screens/generate-refused-setting.xml +++ b/internal/guard/testdata/screens/generate-refused-setting.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,12 +136,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -290,10 +282,8 @@ Settings for png - - - - + + @@ -331,15 +321,13 @@ - - - - - png: Width cannot be "99999" - it takes a whole number of pixels from 1 to 20000 - + + + + png: Width cannot be "99999" - it takes a whole number of pixels from 1 to 20000 - - + + @@ -373,12 +361,10 @@ - + - - - width times height cannot pass 40 megapixels, because the picture is held in memory while it is encoded - + + width times height cannot pass 40 megapixels, because the picture is held in memory while it is encoded @@ -411,10 +397,8 @@ Output - - - - + + @@ -544,15 +528,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · png · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · png · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-refused.xml b/internal/guard/testdata/screens/generate-refused.xml index 2b3bdfd..f3d432d 100644 --- a/internal/guard/testdata/screens/generate-refused.xml +++ b/internal/guard/testdata/screens/generate-refused.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -143,29 +137,25 @@ - + - - - 1 B - + + 1 B - - - - - AVIF cannot be smaller than 311 B - the smallest picture this format draws codes to 303 - B at worst, and the file always carries a free box, which costs 8 B even when it holds - nothing. Requested: 1 B. Ask for 311 B or more, or set a smaller width and height, or a - lower quality - + + + + AVIF cannot be smaller than 311 B - the smallest picture this format draws codes to 303 + B at worst, and the file always carries a free box, which costs 8 B even when it holds + nothing. Requested: 1 B. Ask for 311 B or more, or set a smaller width and height, or a + lower quality - - + + @@ -312,10 +302,8 @@ Settings for avif - - - - + + @@ -351,10 +339,8 @@ Output - - - - + + @@ -484,15 +470,13 @@ - - - - - 1 file · 1 B · avif · will go to /tfg/out - + + + + 1 file · 1 B · avif · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-switch-by-key.xml b/internal/guard/testdata/screens/generate-switch-by-key.xml index 4b17e1b..3451cb0 100644 --- a/internal/guard/testdata/screens/generate-switch-by-key.xml +++ b/internal/guard/testdata/screens/generate-switch-by-key.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,12 +136,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -290,10 +282,8 @@ Settings for avif - - - - + + @@ -329,10 +319,8 @@ Output - - - - + + @@ -462,15 +450,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-typed.xml b/internal/guard/testdata/screens/generate-typed.xml index e31c12d..92444fb 100644 --- a/internal/guard/testdata/screens/generate-typed.xml +++ b/internal/guard/testdata/screens/generate-typed.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,26 +136,22 @@ - + - - - - + + - - - - - Size "abc" has no number: write something like 10mb or 1048576 - + + + + Size "abc" has no number: write something like 10mb or 1048576 - - + + @@ -301,10 +291,8 @@ Settings for avif - - - - + + @@ -340,10 +328,8 @@ Output - - - - + + @@ -473,15 +459,13 @@ - - - - - Files will go to /tfg/out - + + + + Files will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate-unchecked.xml b/internal/guard/testdata/screens/generate-unchecked.xml index a3f14b0..51135a4 100644 --- a/internal/guard/testdata/screens/generate-unchecked.xml +++ b/internal/guard/testdata/screens/generate-unchecked.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,12 +136,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -290,10 +282,8 @@ Settings for avif - - - - + + @@ -329,10 +319,8 @@ Output - - - - + + @@ -461,15 +449,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/generate.xml b/internal/guard/testdata/screens/generate.xml index 6dd1326..54ebb5f 100644 --- a/internal/guard/testdata/screens/generate.xml +++ b/internal/guard/testdata/screens/generate.xml @@ -36,21 +36,17 @@ - - - - - Single batch - + + + + Single batch - - - + + + - - - Files of one format and one size, with a manifest that says how the system under test should react to them. - + + Files of one format and one size, with a manifest that says how the system under test should react to them. @@ -73,10 +69,8 @@ File configuration - - - - + + @@ -142,12 +136,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -290,10 +282,8 @@ Settings for avif - - - - + + @@ -329,10 +319,8 @@ Output - - - - + + @@ -462,15 +450,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/preset-many-settings.xml b/internal/guard/testdata/screens/preset-many-settings.xml index 3b16f3d..0145481 100644 --- a/internal/guard/testdata/screens/preset-many-settings.xml +++ b/internal/guard/testdata/screens/preset-many-settings.xml @@ -36,21 +36,17 @@ - - - - - Presets - + + + + Presets - - - + + + - - - Ready-made sets of files, each built to answer one question about the system under test. - + + Ready-made sets of files, each built to answer one question about the system under test. @@ -73,10 +69,8 @@ The question - - - - + + @@ -113,96 +107,80 @@ - - - - - Does my upload form take what it should and turn the rest away? - + + + + Does my upload form take what it should and turn the rest away? - - - - - - - Typically finds: - + + + + + + Typically finds: - - + + • - - - - - a limit enforced in the browser and not on the server - + + + + a limit enforced in the browser and not on the server - - + + • - - - - - an SVG or an HTML file taken for a picture or for plain text, which is a way to get a script past a form - + + + + an SVG or an HTML file taken for a picture or for plain text, which is a way to get a script past a form - - + + • - - - - - a file checked by its extension and never opened, so a PDF named .jpg goes through - + + + + a file checked by its extension and never opened, so a PDF named .jpg goes through - - + + • - - - - - a form that reads the whole body into memory before it looks at how big it is - + + + + a form that reads the whole body into memory before it looks at how big it is - - + + • - - - - - an upload named PHOTO.JPG turned away where photo.jpg is taken, or the other way round - + + + + an upload named PHOTO.JPG turned away where photo.jpg is taken, or the other way round - - + + • - - - - - a name with spaces, brackets or characters outside ASCII written to disk unchanged - + + + + a name with spaces, brackets or characters outside ASCII written to disk unchanged - - + + @@ -227,10 +205,8 @@ Settings - - - - + + @@ -269,12 +245,10 @@ - + - - - - + + @@ -422,10 +396,8 @@ Output - - - - + + @@ -532,15 +504,13 @@ - - - - - 71 files · 115.1 MB (120 639 488 B) · 6 formats · will go to /tfg/out - + + + + 71 files · 115.1 MB (120 639 488 B) · 6 formats · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/preset-menu-setting.xml b/internal/guard/testdata/screens/preset-menu-setting.xml index 42fcc20..4c6533b 100644 --- a/internal/guard/testdata/screens/preset-menu-setting.xml +++ b/internal/guard/testdata/screens/preset-menu-setting.xml @@ -36,21 +36,17 @@ - - - - - Presets - + + + + Presets - - - + + + - - - Ready-made sets of files, each built to answer one question about the system under test. - + + Ready-made sets of files, each built to answer one question about the system under test. @@ -73,10 +69,8 @@ The question - - - - + + @@ -113,60 +107,50 @@ - - - - - Is a size limit enforced exactly where it is declared? - + + + + Is a size limit enforced exactly where it is declared? - - - - - - - Typically finds: - + + + + + + Typically finds: - - + + • - - - - - off by one errors at the limit - + + + + off by one errors at the limit - - + + • - - - - - MB confused with MiB, which is 4.8 per cent and enough to let a file through that should not pass - + + + + MB confused with MiB, which is 4.8 per cent and enough to let a file through that should not pass - - + + • - - - - - a limit enforced in the browser and not on the server - + + + + a limit enforced in the browser and not on the server - - + + @@ -191,10 +175,8 @@ Settings - - - - + + @@ -233,12 +215,10 @@ - + - - - - + + @@ -325,10 +305,8 @@ Output - - - - + + @@ -435,15 +413,13 @@ - - - - - 7 files · 70.0 MB (73 400 320 B) · pdf · will go to /tfg/out - + + + + 7 files · 70.0 MB (73 400 320 B) · pdf · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/preset-menu.xml b/internal/guard/testdata/screens/preset-menu.xml index cda8f82..e658e2b 100644 --- a/internal/guard/testdata/screens/preset-menu.xml +++ b/internal/guard/testdata/screens/preset-menu.xml @@ -36,21 +36,17 @@ - - - - - Presets - + + + + Presets - - - + + + - - - Ready-made sets of files, each built to answer one question about the system under test. - + + Ready-made sets of files, each built to answer one question about the system under test. @@ -73,10 +69,8 @@ The question - - - - + + @@ -113,72 +107,60 @@ - - - - - Does a file that is valid and as small as the format allows get through? - + + + + Does a file that is valid and as small as the format allows get through? - - - - - - - Typically finds: - + + + + + + Typically finds: - - + + • - - - - - a valid file turned away for being too small, where the check counts bytes instead of reading them - + + + + a valid file turned away for being too small, where the check counts bytes instead of reading them - - + + • - - - - - an empty file that brings the reader down rather than being reported - + + + + an empty file that brings the reader down rather than being reported - - + + • - - - - - a picture one pixel wide that divides by zero on the way to a thumbnail - + + + + a picture one pixel wide that divides by zero on the way to a thumbnail - - + + • - - - - - storage that reads nought bytes as a failed upload and keeps retrying - + + + + storage that reads nought bytes as a failed upload and keeps retrying - - + + @@ -203,10 +185,8 @@ Settings - - - - + + @@ -269,10 +249,8 @@ Output - - - - + + @@ -379,15 +357,13 @@ - - - - - 28 files · 31.9 KB (32 667 B) · 26 formats · will go to /tfg/out - + + + + 28 files · 31.9 KB (32 667 B) · 26 formats · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/preset-refused.xml b/internal/guard/testdata/screens/preset-refused.xml index 9b359ba..f3d2d05 100644 --- a/internal/guard/testdata/screens/preset-refused.xml +++ b/internal/guard/testdata/screens/preset-refused.xml @@ -36,21 +36,17 @@ - - - - - Presets - + + + + Presets - - - + + + - - - Ready-made sets of files, each built to answer one question about the system under test. - + + Ready-made sets of files, each built to answer one question about the system under test. @@ -73,10 +69,8 @@ The question - - - - + + @@ -113,60 +107,50 @@ - - - - - Is a size limit enforced exactly where it is declared? - + + + + Is a size limit enforced exactly where it is declared? - - - - - - - Typically finds: - + + + + + + Typically finds: - - + + • - - - - - off by one errors at the limit - + + + + off by one errors at the limit - - + + • - - - - - MB confused with MiB, which is 4.8 per cent and enough to let a file through that should not pass - + + + + MB confused with MiB, which is 4.8 per cent and enough to let a file through that should not pass - - + + • - - - - - a limit enforced in the browser and not on the server - + + + + a limit enforced in the browser and not on the server - - + + @@ -191,10 +175,8 @@ Settings - - - - + + @@ -231,28 +213,24 @@ - + - - - 512 B - + + 512 B - - - - - the preset size-boundaries cannot build this set - under_1mb would be -1048064 B, and a file cannot be smaller than - nothing. Raise the Limit above 1051991 B, narrow the spread, or choose a format with a smaller minimum. The Limit - asked for was 512 B. - + + + + the preset size-boundaries cannot build this set - under_1mb would be -1048064 B, and a file cannot be smaller than + nothing. Raise the Limit above 1051991 B, narrow the spread, or choose a format with a smaller minimum. The Limit + asked for was 512 B. - - + + @@ -336,10 +314,8 @@ Output - - - - + + @@ -446,15 +422,13 @@ - - - - - Files will go to /tfg/out - + + + + Files will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/preset.xml b/internal/guard/testdata/screens/preset.xml index a16cefb..8f60917 100644 --- a/internal/guard/testdata/screens/preset.xml +++ b/internal/guard/testdata/screens/preset.xml @@ -36,21 +36,17 @@ - - - - - Presets - + + + + Presets - - - + + + - - - Ready-made sets of files, each built to answer one question about the system under test. - + + Ready-made sets of files, each built to answer one question about the system under test. @@ -73,10 +69,8 @@ The question - - - - + + @@ -113,72 +107,60 @@ - - - - - Does a file that is valid and as small as the format allows get through? - + + + + Does a file that is valid and as small as the format allows get through? - - - - - - - Typically finds: - + + + + + + Typically finds: - - + + • - - - - - a valid file turned away for being too small, where the check counts bytes instead of reading them - + + + + a valid file turned away for being too small, where the check counts bytes instead of reading them - - + + • - - - - - an empty file that brings the reader down rather than being reported - + + + + an empty file that brings the reader down rather than being reported - - + + • - - - - - a picture one pixel wide that divides by zero on the way to a thumbnail - + + + + a picture one pixel wide that divides by zero on the way to a thumbnail - - + + • - - - - - storage that reads nought bytes as a failed upload and keeps retrying - + + + + storage that reads nought bytes as a failed upload and keeps retrying - - + + @@ -203,10 +185,8 @@ Settings - - - - + + @@ -269,10 +249,8 @@ Output - - - - + + @@ -379,15 +357,13 @@ - - - - - 28 files · 31.9 KB (32 667 B) · 26 formats · will go to /tfg/out - + + + + 28 files · 31.9 KB (32 667 B) · 26 formats · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/recipe-contents.xml b/internal/guard/testdata/screens/recipe-contents.xml index 4687fb4..e1a2ea2 100644 --- a/internal/guard/testdata/screens/recipe-contents.xml +++ b/internal/guard/testdata/screens/recipe-contents.xml @@ -36,21 +36,17 @@ - - - - - Several batches - + + + + Several batches - - - + + + - - - Batches of different formats and sizes, generated together in one run. - + + Batches of different formats and sizes, generated together in one run. @@ -74,10 +70,8 @@ Build on a preset - - - - + + @@ -86,13 +80,11 @@ - + - - - With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole - recipe. - + + With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole + recipe. @@ -133,8 +125,8 @@ - - + + @@ -142,10 +134,8 @@ Batch 1 - - - - + + @@ -265,12 +255,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -359,10 +347,8 @@ Settings for zip - - - - + + @@ -395,10 +381,8 @@ Notes for the manifest - - - - + + @@ -411,15 +395,13 @@ - - - - - Files inside each archive - + + + + Files inside each archive - - + + Format @@ -530,10 +512,8 @@ Output - - - - + + @@ -695,15 +675,13 @@ - - - - - Files will go to /tfg/out - + + + + Files will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/recipe-on-a-preset.xml b/internal/guard/testdata/screens/recipe-on-a-preset.xml index 11adb13..a23c2e4 100644 --- a/internal/guard/testdata/screens/recipe-on-a-preset.xml +++ b/internal/guard/testdata/screens/recipe-on-a-preset.xml @@ -36,21 +36,17 @@ - - - - - Several batches - + + + + Several batches - - - + + + - - - Batches of different formats and sizes, generated together in one run. - + + Batches of different formats and sizes, generated together in one run. @@ -74,10 +70,8 @@ Build on a preset - - - - + + @@ -86,13 +80,11 @@ - + - - - With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole - recipe. - + + With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole + recipe. @@ -192,8 +184,8 @@ - - + + @@ -201,10 +193,8 @@ Batch 1 - - - - + + @@ -329,12 +319,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -423,10 +411,8 @@ Settings for avif - - - - + + @@ -459,10 +445,8 @@ Notes for the manifest - - - - + + @@ -498,10 +482,8 @@ Output - - - - + + @@ -663,15 +645,13 @@ - - - - - 29 files · 10.0 MB (10 518 427 B) · 26 formats · will go to /tfg/out - + + + + 29 files · 10.0 MB (10 518 427 B) · 26 formats · will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/recipe-refused-with-one-batch-filled.xml b/internal/guard/testdata/screens/recipe-refused-with-one-batch-filled.xml index 6f6b4f8..16f6acf 100644 --- a/internal/guard/testdata/screens/recipe-refused-with-one-batch-filled.xml +++ b/internal/guard/testdata/screens/recipe-refused-with-one-batch-filled.xml @@ -36,21 +36,17 @@ - - - - - Several batches - + + + + Several batches - - - + + + - - - Batches of different formats and sizes, generated together in one run. - + + Batches of different formats and sizes, generated together in one run. @@ -74,10 +70,8 @@ Build on a preset - - - - + + @@ -86,13 +80,11 @@ - + - - - With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole - recipe. - + + With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole + recipe. @@ -133,8 +125,8 @@ - - + + @@ -142,10 +134,8 @@ Batch 1 - - - - + + @@ -273,28 +263,24 @@ - + - - - - + + - - - - - target 1 has no Size - every target declares its Size, which is what lets a dry run report exact numbers before anything - reaches the disk. - add size: 2mb, size-range: 1kb-8kb, a boundary, contains, or a plain number of bytes. - + + + + target 1 has no Size - every target declares its Size, which is what lets a dry run report exact numbers before anything + reaches the disk. + add size: 2mb, size-range: 1kb-8kb, a boundary, contains, or a plain number of bytes. - - + + @@ -332,17 +318,15 @@ - - - - - target 1 has no Batch name - a Batch name anchors the seed of a target, so editing one - target never moves the bytes of another. - give it a Batch name, for example id: invoices. - + + + + target 1 has no Batch name - a Batch name anchors the seed of a target, so editing one + target never moves the bytes of another. + give it a Batch name, for example id: invoices. - - + + @@ -397,10 +381,8 @@ Settings for avif - - - - + + @@ -433,10 +415,8 @@ Notes for the manifest - - - - + + @@ -460,8 +440,8 @@ - - + + @@ -469,10 +449,8 @@ Batch 2 - - - - + + @@ -597,12 +575,10 @@ - + - - - 1 024 B - + + 1 024 B @@ -691,10 +667,8 @@ Settings for avif - - - - + + @@ -727,10 +701,8 @@ Notes for the manifest - - - - + + @@ -766,10 +738,8 @@ Output - - - - + + @@ -939,15 +909,13 @@ - - - - - Files will go to /tfg/out - + + + + Files will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/recipe-refused.xml b/internal/guard/testdata/screens/recipe-refused.xml index d159e50..856c46e 100644 --- a/internal/guard/testdata/screens/recipe-refused.xml +++ b/internal/guard/testdata/screens/recipe-refused.xml @@ -36,21 +36,17 @@ - - - - - Several batches - + + + + Several batches - - - + + + - - - Batches of different formats and sizes, generated together in one run. - + + Batches of different formats and sizes, generated together in one run. @@ -74,10 +70,8 @@ Build on a preset - - - - + + @@ -86,13 +80,11 @@ - + - - - With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole - recipe. - + + With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole + recipe. @@ -133,8 +125,8 @@ - - + + @@ -142,10 +134,8 @@ Batch 1 - - - - + + @@ -268,28 +258,24 @@ - + - - - - + + - - - - - target 1 has no Size - every target declares its Size, which is what lets a dry run report exact numbers before anything - reaches the disk. - add size: 2mb, size-range: 1kb-8kb, a boundary, contains, or a plain number of bytes. - + + + + target 1 has no Size - every target declares its Size, which is what lets a dry run report exact numbers before anything + reaches the disk. + add size: 2mb, size-range: 1kb-8kb, a boundary, contains, or a plain number of bytes. - - + + @@ -327,17 +313,15 @@ - - - - - target 1 has no Batch name - a Batch name anchors the seed of a target, so editing one - target never moves the bytes of another. - give it a Batch name, for example id: invoices. - + + + + target 1 has no Batch name - a Batch name anchors the seed of a target, so editing one + target never moves the bytes of another. + give it a Batch name, for example id: invoices. - - + + @@ -392,10 +376,8 @@ Settings for avif - - - - + + @@ -428,10 +410,8 @@ Notes for the manifest - - - - + + @@ -467,10 +447,8 @@ Output - - - - + + @@ -632,15 +610,13 @@ - - - - - Files will go to /tfg/out - + + + + Files will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/recipe-two-batches.xml b/internal/guard/testdata/screens/recipe-two-batches.xml index d12eabf..d7c2c96 100644 --- a/internal/guard/testdata/screens/recipe-two-batches.xml +++ b/internal/guard/testdata/screens/recipe-two-batches.xml @@ -36,21 +36,17 @@ - - - - - Several batches - + + + + Several batches - - - + + + - - - Batches of different formats and sizes, generated together in one run. - + + Batches of different formats and sizes, generated together in one run. @@ -74,10 +70,8 @@ Build on a preset - - - - + + @@ -86,13 +80,11 @@ - + - - - With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole - recipe. - + + With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole + recipe. @@ -133,8 +125,8 @@ - - + + @@ -142,10 +134,8 @@ Batch 1 - - - - + + @@ -270,12 +260,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -364,10 +352,8 @@ Settings for avif - - - - + + @@ -400,10 +386,8 @@ Notes for the manifest - - - - + + @@ -427,8 +411,8 @@ - - + + @@ -436,10 +420,8 @@ Batch 2 - - - - + + @@ -567,12 +549,10 @@ - + - - - - + + @@ -664,10 +644,8 @@ Settings for avif - - - - + + @@ -700,10 +678,8 @@ Notes for the manifest - - - - + + @@ -739,10 +715,8 @@ Output - - - - + + @@ -912,15 +886,13 @@ - - - - - Files will go to /tfg/out - + + + + Files will go to /tfg/out - - + + diff --git a/internal/guard/testdata/screens/recipe.xml b/internal/guard/testdata/screens/recipe.xml index d824209..266bcdf 100644 --- a/internal/guard/testdata/screens/recipe.xml +++ b/internal/guard/testdata/screens/recipe.xml @@ -36,21 +36,17 @@ - - - - - Several batches - + + + + Several batches - - - + + + - - - Batches of different formats and sizes, generated together in one run. - + + Batches of different formats and sizes, generated together in one run. @@ -74,10 +70,8 @@ Build on a preset - - - - + + @@ -86,13 +80,11 @@ - + - - - With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole - recipe. - + + With the box ticked, the chosen preset's files come first and the batches below are added after them. Without it, the batches are the whole + recipe. @@ -133,8 +125,8 @@ - - + + @@ -142,10 +134,8 @@ Batch 1 - - - - + + @@ -265,12 +255,10 @@ - + - - - 10 485 760 B - + + 10 485 760 B @@ -359,10 +347,8 @@ Settings for avif - - - - + + @@ -395,10 +381,8 @@ Notes for the manifest - - - - + + @@ -434,10 +418,8 @@ Output - - - - + + @@ -599,15 +581,13 @@ - - - - - 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - + + + + 1 file · 10.0 MB (10 485 760 B) · avif · will go to /tfg/out - - + + diff --git a/internal/guard/themescope_test.go b/internal/guard/themescope_test.go new file mode 100644 index 0000000..a48c840 --- /dev/null +++ b/internal/guard/themescope_test.go @@ -0,0 +1,66 @@ +package guard + +import ( + "testing" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/test" + + "github.com/donislawdev/TestingFilesGenerator/internal/gui/catalogue" + "github.com/donislawdev/TestingFilesGenerator/internal/gui/parts" +) + +// No screen, and nothing in the catalogue of parts, stands in a theme override. +// +// An override is the toolkit's one public door into a subtree's theme, and it +// costs memory that never comes back. Fyne 2.8.1 gives an override a NEW scope +// at construction, at CreateRenderer and at every Refresh, and keys its parsed +// fonts by scope - so every rebuild of a screen followed by a new string drawn +// under an override parsed another ~7.4 MB set of fonts. Measured in the real +// window on 2026-09-23 (tools/probes/guilag, docs/GUI-MEMORY-2026-09-23.md +// section 4c): 26 sets after visiting the tabs, a live heap of 205 MB, and ten +// rebuilds each followed by a new size added 84 MB more. Every sentence, error +// area, caption and count of bytes was under one. Without them: 2 sets, 27 MB, +// and nothing added by the rebuilds. +// +// The open list of formats is not on this screen - it is a popup - and it +// still draws its rows under one (parts/openlist.go, rowTheme). That is the +// next thing the same document names, and it is named here so that nobody +// reads this guard as covering it. +func TestNoScreenStandsInAThemeOverride(t *testing.T) { + content, _ := laidOutWindow(t) + + quiet, counts := 0, 0 + walk(content, func(o fyne.CanvasObject) { + switch o.(type) { + case *parts.QuietText: + quiet++ + case *parts.ByteCount: + counts++ + } + }) + // The things that stood under an override until 2026-09-23 have to be on + // the screen for their absence from one to mean anything: a subtitle on + // each of three work screens, and the count of bytes beside a size. + if quiet < 3 || counts < 1 { + t.Fatalf("the window holds %d quiet line(s) and %d count(s) of bytes, so this guard is not "+ + "looking at the screens it asks about", quiet, counts) + } + + cat := test.NewWindow(catalogue.Screen()) + t.Cleanup(cat.Close) + + for name, root := range map[string]fyne.CanvasObject{"the window": content, "the catalogue": cat.Content()} { + overrides := 0 + walk(root, func(o fyne.CanvasObject) { + if _, is := o.(*container.ThemeOverride); is { + overrides++ + } + }) + if overrides > 0 { + t.Errorf("%s holds %d theme override(s), and each one parses the fonts again in a scope of its own - "+ + "take the room off with a layout (inkTight) and name the colour in the words (QuietText)", name, overrides) + } + } +} diff --git a/internal/guard/words_test.go b/internal/guard/words_test.go index 7deff14..b263e34 100644 --- a/internal/guard/words_test.go +++ b/internal/guard/words_test.go @@ -4,6 +4,8 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/widget" + + "github.com/donislawdev/TestingFilesGenerator/internal/gui/parts" ) // wordsOf is the text an object shows, whichever of the two kinds of object @@ -19,6 +21,10 @@ import ( // one place the two kinds are told apart, so the next kind is one more case // here rather than a hunt through thirty type assertions. // +// The third kind since 2026-09-23: parts.QuietText, the words that recede - +// a subtitle, a caption, a folded section's line, the count of bytes - which +// stopped being toolkit labels under a theme override (see QuietText). +// // A hidden object still answers. Whether something is on the screen is a // question about its ancestors as well, and sizechoice_test.go asks it // properly. Nothing here filters. @@ -28,6 +34,10 @@ func wordsOf(o fyne.CanvasObject) (string, bool) { return v.Text, true case *canvas.Text: return v.Text, true + case *parts.QuietText: + return v.Text, true + case *parts.ByteCount: + return v.Text, true } return "", false } @@ -46,6 +56,20 @@ func boldWordsAt(o fyne.CanvasObject) (text string, bold bool, size float32, ok return v.Text, v.TextStyle.Bold, fyne.CurrentApp().Settings().Theme().Size(name), true case *canvas.Text: return v.Text, v.TextStyle.Bold, v.TextSize, true + case *parts.QuietText: + return v.Text, false, quietSize(v), true + case *parts.ByteCount: + return v.Text, false, quietSize(&v.QuietText), true } return "", false, 0, false } + +// quietSize is the size quiet words are drawn at: their rank of the scale, +// the body text when none is named - the rule widget.Label keeps. +func quietSize(q *parts.QuietText) float32 { + name := q.SizeName + if name == "" { + name = "text" + } + return fyne.CurrentApp().Settings().Theme().Size(name) +} diff --git a/internal/gui/catalogue/words.go b/internal/gui/catalogue/words.go index 9eb2168..454757a 100644 --- a/internal/gui/catalogue/words.go +++ b/internal/gui/catalogue/words.go @@ -13,7 +13,7 @@ import ( // thing a person looks at as a whole, which is why every rank is here once, // one under another, and once more with a long line to see where it wraps. func textRanks() Entry { - return Entry{Name: "Title", Covers: []string{"Subtitle", "Titled", "Heading", "Subheading", "Prose", "Note", "Caption", "Bullets", "Ledger"}, States: []State{ + return Entry{Name: "Title", Covers: []string{"Subtitle", "Titled", "Heading", "Subheading", "Prose", "Note", "Caption", "QuietText", "Bullets", "Ledger"}, States: []State{ {"the title of a screen", func() fyne.CanvasObject { return parts.Title("Single batch") }}, {"the sentence under a title", func() fyne.CanvasObject { return parts.Subtitle("Files of one format and one size, with a manifest that says how the system under test should react to them.") diff --git a/internal/gui/parts/bytecount.go b/internal/gui/parts/bytecount.go index e4c6495..89d3923 100644 --- a/internal/gui/parts/bytecount.go +++ b/internal/gui/parts/bytecount.go @@ -2,7 +2,6 @@ package parts import ( "fyne.io/fyne/v2/theme" - "fyne.io/fyne/v2/widget" "github.com/donislawdev/TestingFilesGenerator/internal/core" ) @@ -28,18 +27,21 @@ import ( // Spelled by core.ExactBytes, which is what the command line prints. The // window had a spelling of its own without the grouping until 2026-09-14, so // one number came out as 10485760 B here and 10 485 760 B there. +// +// Quiet words since 2026-09-23, rather than a low importance label under a +// theme override - see QuietText for what the override cost. type ByteCount struct { - widget.Label + QuietText } func newByteCount() *ByteCount { c := &ByteCount{} + c.start("") c.ExtendBaseWidget(c) // The same rank as the line explaining a field, because it is the same kind // of thing: something quiet beside a control that the eye should skip until // it wants it. c.SizeName = theme.SizeNameCaptionText - c.Importance = widget.LowImportance return c } diff --git a/internal/gui/parts/field.go b/internal/gui/parts/field.go index 2f8309d..716d7c4 100644 --- a/internal/gui/parts/field.go +++ b/internal/gui/parts/field.go @@ -130,16 +130,15 @@ func shapedForItsValues(control fyne.CanvasObject) fyne.CanvasObject { // worse than the italics it was replacing. So it went in as ordinary text // until the palette arrived. // -// It goes through quiet rather than inkTight since 2026-09-15, which is O213: +// It is QuietText since 2026-09-23 and was a quiet label before, which is O213: // widget.LowImportance draws in ColorNameDisabled, #C2C8CD at 80 L*, a step -// brighter than the hint a caption is meant to be. quiet remaps it to the +// brighter than the hint a caption is meant to be. QuietText draws the // placeholder, #9DA3A8 at 66.7 L*, 5.61:1 on a panel. O70 and O71. func Note(content string) fyne.CanvasObject { - label := widget.NewLabel(content) - label.Wrapping = fyne.TextWrapWord - label.Importance = widget.LowImportance - label.SizeName = theme.SizeNameCaptionText - return quiet(label) + note := NewQuietText(content) + note.Wrapping = fyne.TextWrapWord + note.SizeName = theme.SizeNameCaptionText + return note } // ErrorArea is where a field says what a run said about it. diff --git a/internal/gui/parts/fields.go b/internal/gui/parts/fields.go index d944505..9ae19b2 100644 --- a/internal/gui/parts/fields.go +++ b/internal/gui/parts/fields.go @@ -226,10 +226,9 @@ func (s *Fields) counter(setting string, control fyne.CanvasObject) fyne.CanvasO // Beside the box on its own line, with no room of its own around the ink, // so what the row puts between the box and the count is what reaches the // screen. Until 2026-09-14 it stood at the far end of the name's line, 190 - // px from the box it was counting for. Drawn through quiet since 2026-09-15 - // - it is a low importance label, so the same O213 that dimmed a caption - // dimmed this. See parts.quiet. - return quiet(count) + // px from the box it was counting for. Quiet words since 2026-09-15 - the + // same O213 that dimmed a caption dimmed this. See QuietText. + return count } // Add builds a field and hands back the thing to put on the screen. diff --git a/internal/gui/parts/folding.go b/internal/gui/parts/folding.go index 4629234..faa8b01 100644 --- a/internal/gui/parts/folding.go +++ b/internal/gui/parts/folding.go @@ -36,7 +36,7 @@ type Folding struct { open bool title string body fyne.CanvasObject - line *widget.Label + line *QuietText // head is the one control the whole head row is - see FoldHead. head *FoldHead @@ -167,8 +167,7 @@ type groupCell struct{ wideCell } func newFolding(title string, titled fyne.CanvasObject, head []fyne.CanvasObject, content ...fyne.CanvasObject) *Folding { f := &Folding{open: true, title: title} - f.line = widget.NewLabel("") - f.line.Importance = widget.LowImportance + f.line = NewQuietText("") f.line.Hide() f.body = Grid(content...) @@ -182,7 +181,7 @@ func newFolding(title string, titled fyne.CanvasObject, head []fyne.CanvasObject // (TestEverythingAPersonReadsStartsOnOneLeftEdge). Indenting the section's // contents to match would put its fields off that edge instead, which is // worse - there are more of them and they are what somebody is reading. - // The summary line goes through quiet, so it recedes to the hint's colour + // The summary line is QuietText, so it recedes to the hint's colour // rather than the brighter disabled one widget.LowImportance draws (O213). // // The whole row is the control, since O221, and the arrow is its mark @@ -198,7 +197,14 @@ func newFolding(title string, titled fyne.CanvasObject, head []fyne.CanvasObject // words it was a 6 px triangle at the end of a heading, and the heading // read as an orphaned subtitle rather than as something that opens. The // arrow now stands on the left edge and the words start after it. - words := Padded(TabInset, container.NewHBox(arrow, titled, quiet(f.line))) + // + // The line stands in a container of its own that never hides, so the row + // keeps the gap before it even while the line is hidden - which is how the + // head of an open section gets as much room after its title as before its + // arrow. The line sat inside a theme override until 2026-09-23, and it was + // the override that stayed visible. Taking the override away took 4 px off + // the right of every open head, measured on the stored catalogue. + words := Padded(TabInset, container.NewHBox(arrow, titled, container.NewStack(f.line))) f.head.under = words row := container.NewBorder(nil, nil, nil, ButtonRow(head...), container.NewStack(f.head, words)) diff --git a/internal/gui/parts/parts.go b/internal/gui/parts/parts.go index 8017a66..787f8de 100644 --- a/internal/gui/parts/parts.go +++ b/internal/gui/parts/parts.go @@ -21,8 +21,6 @@ package parts import ( - "image/color" - "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" @@ -118,18 +116,17 @@ func oneLine(text string, size fyne.ThemeSizeName) fyne.CanvasObject { // hint rather than of a value, so it reads as an explanation of the word above // it and not as a second heading competing with it. // -// A toolkit label rather than canvas words, because a sentence wraps and a +// Wrapping words rather than canvas words, because a sentence wraps and a // name does not - the same split words and Prose make. Its colour is the // hint's, the same step the words on the strip stand at when they are not -// chosen, so the head of a screen has one quiet colour and not two. Asked for -// through quiet below, because the toolkit draws a low importance label in the -// DISABLED colour, and this palette keeps that a step brighter than a hint on -// purpose - see ColorNameDisabled in theme.go. +// chosen, so the head of a screen has one quiet colour and not two. QuietText, +// because the toolkit draws a low importance label in the DISABLED colour, and +// this palette keeps that a step brighter than a hint on purpose - see +// ColorNameDisabled in theme.go. func Subtitle(sentence string) fyne.CanvasObject { - label := widget.NewLabel(sentence) - label.Wrapping = fyne.TextWrapWord - label.Importance = widget.LowImportance - return quiet(label) + subtitle := NewQuietText(sentence) + subtitle.Wrapping = fyne.TextWrapWord + return subtitle } // Caption is a short quiet line over or under a thing, at the smallest rank @@ -138,39 +135,10 @@ func Subtitle(sentence string) fyne.CanvasObject { // on 2026-09-15 when a second thing needed it - a rank used twice without a // name is GUI rule 7's definition of a missing style. func Caption(text string) fyne.CanvasObject { - label := widget.NewLabel(text) - label.Wrapping = fyne.TextWrapWord - label.SizeName = theme.SizeNameCaptionText - label.Importance = widget.LowImportance - return quiet(label) -} - -// quiet draws a low importance label in the hint's colour rather than the -// disabled one, and takes the room a label keeps around itself off it. -// -// One helper rather than one at each call site, because O213 was four call -// sites saying different things: a caption under a field, the count of bytes, a -// folded section's summary and this subtitle were all widget.LowImportance, -// which the toolkit draws in ColorNameDisabled - #C2C8CD, 80 L*, a step -// BRIGHTER than a hint. So a caption meant to recede sat louder than the -// placeholder in an empty box beside it. Owner's decision on 2026-09-15: one -// quiet, the hint's, and the disabled colour kept for a value that is switched -// off - which is content somebody may want to re-read and so is right to be the -// brighter of the two. -func quiet(o fyne.CanvasObject) fyne.CanvasObject { - return container.NewThemeOverride(o, quietInk{noInnerPadding{Theme()}}) -} - -// quietInk is the window's theme with a low importance label drawn in the -// hint's colour rather than the disabled one, and without the room a label -// keeps around itself. -type quietInk struct{ noInnerPadding } - -func (q quietInk) Color(name fyne.ThemeColorName, variant fyne.ThemeVariant) color.Color { - if name == theme.ColorNameDisabled { - return q.noInnerPadding.Color(theme.ColorNamePlaceHolder, variant) - } - return q.noInnerPadding.Color(name, variant) + caption := NewQuietText(text) + caption.Wrapping = fyne.TextWrapWord + caption.SizeName = theme.SizeNameCaptionText + return caption } // Titled is what stands above a screen's sections: its name, and under it the diff --git a/internal/gui/parts/quiet.go b/internal/gui/parts/quiet.go new file mode 100644 index 0000000..f28dc54 --- /dev/null +++ b/internal/gui/parts/quiet.go @@ -0,0 +1,97 @@ +package parts + +import ( + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/theme" + "fyne.io/fyne/v2/widget" +) + +// QuietText is words that recede: a screen's subtitle, a caption, the line a +// folded section keeps, the count of bytes beside a size. Drawn in the hint's +// colour, with no room of its own around the ink. +// +// The hint's colour and not the disabled one is O213, the owner's decision of +// 2026-09-15: the toolkit draws a low importance label in ColorNameDisabled, +// #C2C8CD at 80 L*, a step BRIGHTER than a hint - so a caption meant to recede +// sat louder than the placeholder in an empty box beside it. The disabled +// colour stays for a value that is switched off. +// +// Its own widget rather than a toolkit label under a theme override, since +// 2026-09-23. A label's colour follows its importance and nothing else, so the +// only way to give it the hint's colour was an override - and Fyne gives an +// override a new scope at construction, at CreateRenderer and at every +// Refresh, and parses a fresh ~7.4 MB set of fonts for every scope a new +// string is drawn in. Measured in the real window: ten rebuilds of the batch +// screen, each followed by a new size, parsed ten sets for the count of bytes +// alone, and nothing frees them (docs/GUI-MEMORY-2026-09-23.md section 4c). +// A rich text names its colour per segment, so none of that is needed. +// +// The segment is the one widget.Label builds for itself (widget/label.go, +// syncSegments), with the colour changed and nothing else, and the room is +// taken off by the layout inkTight uses - so what reaches the screen is what +// the label under the override drew, pixel for pixel on every stored screen. +// +// Like a label it does not wrap unless asked to. +type QuietText struct { + widget.BaseWidget + + // Text is what it says, SizeName the rank of the scale it says it at + // (the body text when empty), and Wrapping whether a long line breaks. + Text string + SizeName fyne.ThemeSizeName + Wrapping fyne.TextWrap + + rich *widget.RichText +} + +// NewQuietText makes quiet words. +func NewQuietText(text string) *QuietText { + q := &QuietText{} + q.start(text) + q.ExtendBaseWidget(q) + return q +} + +// start is what every QuietText needs before it is drawn, a ByteCount +// included - which is a QuietText inside and extends itself rather than this. +func (q *QuietText) start(text string) { + q.Text = text + q.rich = widget.NewRichText(&widget.TextSegment{}) +} + +// SetText changes what it says. +func (q *QuietText) SetText(text string) { + q.Text = text + q.Refresh() +} + +// Refresh carries the fields into the segment before anything is redrawn. +// The rich text is refreshed once, by the renderer through its container - +// widget.Label refreshes its own twice, which a count redrawn on every key +// has no need of. +func (q *QuietText) Refresh() { + q.sync() + q.BaseWidget.Refresh() +} + +// CreateRenderer draws the rich text ink tight. +func (q *QuietText) CreateRenderer() fyne.WidgetRenderer { + q.sync() + return widget.NewSimpleRenderer(inkTight(q.rich)) +} + +// sync is widget.Label's syncSegments with the hint's colour. +func (q *QuietText) sync() { + size := q.SizeName + if size == "" { + size = theme.SizeNameText + } + q.rich.Wrapping = q.Wrapping + segment := q.rich.Segments[0].(*widget.TextSegment) + segment.Text = q.Text + segment.Style = widget.RichTextStyle{ + ColorName: theme.ColorNamePlaceHolder, + Inline: true, + SizeName: size, + } +} diff --git a/internal/gui/parts/words.go b/internal/gui/parts/words.go index 5123b3a..6218f96 100644 --- a/internal/gui/parts/words.go +++ b/internal/gui/parts/words.go @@ -35,14 +35,49 @@ func words(text string, size float32, bold bool, colour fyne.ThemeColorName) *ca // inkTight takes the toolkit's own padding off a label, so a sentence that // wraps stands on the scale like everything else. // -// A theme override rather than a widget of ours, because the label keeps -// everything a sentence needs - wrapping, the caption size, the colour an -// importance gives it - and the only thing wrong with it is the room it keeps -// around itself. The override is the toolkit's one public door into a -// subtree's theme, and it is used bare rather than wrapped in a type of ours, -// because the driver casts to it. +// A layout rather than a theme, since 2026-09-23. The label keeps everything a +// sentence needs - wrapping, the caption size, the colour an importance gives +// it - and the only thing wrong with it is the room it keeps around itself, so +// the layout gives it that room outside its own edge: one inner padding larger +// on every side and one inner padding up and to the left. The words land where +// a label with no inner padding would put them and wrap at the same width - +// all 28 stored screens came out pixel for pixel the same. +// +// It was a container.ThemeOverride until then, and that is the reason it is +// not one now. Fyne gives an override a NEW scope at construction, at +// CreateRenderer and at every Refresh, and keys its parsed fonts by scope - so +// every rebuild of a screen followed by a new string in one of these labels +// parsed another ~7.4 MB set of fonts that nothing ever frees. Measured in the +// real window: 19 of the 26 sets after visiting the tabs were this override's, +// and the live heap there went from 205 MB to 64 MB without it +// (docs/GUI-MEMORY-2026-09-23.md section 4c). func inkTight(o fyne.CanvasObject) fyne.CanvasObject { - return container.NewThemeOverride(o, noInnerPadding{Theme()}) + return container.New(inkTightLayout{}, o) +} + +// inkTightLayout places a label so that its inner padding falls outside the +// room it is given - see inkTight. A hidden label takes no room, as it did +// inside the override it replaced. +type inkTightLayout struct{} + +func (inkTightLayout) MinSize(objects []fyne.CanvasObject) fyne.Size { + pad := Theme().Size(theme.SizeNameInnerPadding) + size := fyne.NewSize(0, 0) + for _, o := range objects { + if !o.Visible() { + continue + } + size = size.Max(o.MinSize().Subtract(fyne.NewSquareSize(2 * pad))) + } + return size +} + +func (inkTightLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) { + pad := Theme().Size(theme.SizeNameInnerPadding) + for _, o := range objects { + o.Move(fyne.NewPos(-pad, -pad)) + o.Resize(size.Add(fyne.NewSquareSize(2 * pad))) + } } // Flush puts a label a screen keeps hold of on the edge every other word @@ -51,18 +86,6 @@ func inkTight(o fyne.CanvasObject) fyne.CanvasObject { // - which has to be built by the runner and placed by the bar. func Flush(label *widget.Label) fyne.CanvasObject { return inkTight(label) } -// noInnerPadding is the window's theme with the room inside a label taken out. -// Only that one size, so a box to type in under the same override would still -// be a box. -type noInnerPadding struct{ fyne.Theme } - -func (n noInnerPadding) Size(name fyne.ThemeSizeName) float32 { - if name == theme.SizeNameInnerPadding { - return 0 - } - return n.Theme.Size(name) -} - // Padded keeps one distance from the scale between its edge and its content. // // The toolkit's padded container reads the theme's padding, which is the