Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions App/Views/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,21 @@ It reads as cosmetic and is not: the outer capsule's padding was taking the
width the segments needed, so in portrait the labels truncated to 「キ… コ…」.
Look at the labels, not just the outline, when judging a change here.

**And the words do not always fit even then, so the toggle falls back to
icons.** The toolbar's trailing items have a ceiling on their width. On the
11-inch iPad the portrait canvas column still truncated to 「Ca… Co…」 and
「キ… コ…」 after #119, and the landscape one to "Canv…" once a drawing had
run. Pinning the control at its own width kept the words and sent ⟳ and export
into a "•••" overflow instead; in Japanese the toggle went with them, which is
worse. Taking either `ToolbarSpacer` away changed nothing. `CanvasViewToggle`
therefore offers the words and then the icons, through `ViewThatFits`, each
form `fixedSize` so it can never be squeezed into an ellipsis. What that gives,
measured: the words on the 13-inch landscape (both languages), on the Mac (in
Japanese) and the phone's sheet (in English), and English on the 11-inch
landscape; the icons in portrait on
both iPads and for Japanese on the 11-inch landscape. Judge a change here on
the 11-inch, in portrait and in Japanese: that is the narrowest case.

**26's glass is not used on any surface of ours, and that was tested rather
than assumed** (#79). All three candidates were built and looked at, and all
three came back out.
Expand Down
47 changes: 43 additions & 4 deletions App/Views/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -451,18 +451,57 @@ struct CanvasToolbar: ToolbarContent {
}
}

/// The canvas/code segmented toggle, in `CanvasPane`'s toolbar (#23).
/// The canvas/code segmented toggle, in `CanvasPane`'s toolbar (#23): the
/// words when they fit, the icons when they do not.
///
/// **The toolbar's trailing items have a ceiling on how wide they may be, and
/// the words do not always fit under it.** Measured on the 11-inch iPad
/// simulator: in the portrait canvas column a segmented control that was
/// allowed to shrink came out 「Ca… Co…」 and 「キ… コ…」, and in the landscape
/// one "Canv…" once a drawing had run — the truncation #119 fixed on one width
/// was still there on others. Pinning it at its own width (`fixedSize`) kept the words and sent
/// the ⟳ and export buttons into a "•••" overflow instead, and in Japanese the
/// toggle itself went with them. Neither the flexible spacer before it nor the
/// fixed one after it was what ran out: taking each away changed nothing.
///
/// So the words are offered first and the icons second, and `ViewThatFits`
/// takes whichever the toolbar has room for. The toolbar is a little stingier
/// than `fixedSize` would suggest: the 11-inch's landscape column fits the
/// English words but not 「キャンバス」, so Japanese gets the icons there. The
/// 13-inch landscape keeps the words in both languages. VoiceOver reads
/// "Canvas" and "Code" either way.
struct CanvasViewToggle: View {
@Binding var showsCode: Bool

var body: some View {
ViewThatFits(in: .horizontal) {
CanvasViewPicker(showsCode: $showsCode, iconOnly: false)
CanvasViewPicker(showsCode: $showsCode, iconOnly: true)
}
}
}

/// One form of `CanvasViewToggle`, at its own width and never narrower: a
/// segmented control made to shrink truncates its words.
private struct CanvasViewPicker: View {
@Binding var showsCode: Bool
let iconOnly: Bool

var body: some View {
Picker("View", selection: $showsCode) {
Text("Canvas").tag(false)
Text("Code").tag(true)
if iconOnly {
Label("Canvas", systemImage: "scribble.variable").labelStyle(.iconOnly).tag(false)
Label("Code", systemImage: "chevron.left.forwardslash.chevron.right")
.labelStyle(.iconOnly).tag(true)
}
else {
Text("Canvas").tag(false)
Text("Code").tag(true)
}
}
.pickerStyle(.segmented)
.labelsHidden()
.frame(maxWidth: 220)
.fixedSize()
}
}

Expand Down
10 changes: 6 additions & 4 deletions Tools/film/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,12 @@ Repeat, and the first run put a Start Fill where the repeat should have been.
`palette(_:)` scrolls the palette with a finger until the entry is on screen.
Coordinates are used anyway because the log needs the point that was pressed.

**The palette entry is the leftmost button with that label.** "Forward" is
also the transport's step button. It is a separate element with the same name,
and a query that walks its matches one by one lost one between counting and
fetching.
**The palette entry is the leftmost button with that label.** The first run
met a second, disabled button labelled "Forward" as the document opened, and a
query that walked its matches one by one lost one between counting and
fetching. Which button that was was never pinned down: the transport's step
button is "Step Forward", not "Forward", whatever an earlier version of this
note said.

**A hardware keyboard is attached for the run.** The scripts switch the
Simulator's `ConnectHardwareKeyboard` preference on and restart the device to
Expand Down
12 changes: 7 additions & 5 deletions TortoiseBlocksUITests/FilmTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,13 @@

/// A palette entry by its title, scrolled on screen first if it is not.
///
/// The title is not unique: the transport's step button is "Forward"
/// too. Of every button with that label this is the one furthest left,
/// since the palette is the first column — read from one snapshot,
/// because walking a query's matches one by one raced the UI and lost an
/// element between counting and fetching it.
/// The title need not be unique: the first run met a second, disabled
/// button labelled "Forward" as the document opened, and which one it
/// was was never pinned down (the transport's is "Step Forward"). Of
/// every button with the label this is the one furthest left, since the
/// palette is the first column — read from one snapshot, because walking
/// a query's matches one by one raced the UI and lost an element between
/// counting and fetching it.
///
/// **Taps here are coordinates, so nothing scrolls for them.** An
/// element's own `tap()` scrolls it into view; a coordinate below the
Expand Down
2 changes: 1 addition & 1 deletion TortoiseBlocksUITests/MacPreviewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
// MARK: - The hands

/// The leftmost button with this label: the palette is the first
/// column, and "Forward" is the transport's step button too.
/// column, and a label need not be unique (see `FilmTestCase.palette`).
@MainActor
private func palette(_ title: String) throws -> CGRect {
try find(title) { $0.minX < $1.minX }
Expand Down
Loading