Public Access
Give the file listings' columns their content back
The columns in both panes were fixed pixel widths, and measuring them against what they actually draw found them wrong at both ends of the range this screen gets. ◆ MODIFIED WAS TRUNCATED AT EVERY WIDTH THE APPLICATION HAS EVER BEEN DRAWN AT. It prints a sixteen-character timestamp, which needs 116 pixels, and it had 52. On a maximised window that read "2026-08" beside a NAME column with four hundred empty pixels in it. PERMS needs 60 for a ten-character mode and had 48; SIZE needs 58 for "999.9 GB" and had 56. ◆ AND AT THE SESSION SHELL'S OWN NARROWEST, NAME MEASURED ZERO PIXELS. Twenty for the glyph plus 56+52+48 for the numbers is 176 of the 180 a row has, so the remote pane drew sizes, timestamps and modes for rows whose names were not on screen at all. That is the same fault as the one above rather than a second one: the numbers were picked for the narrow budget, could not have fitted their own content there, and never grew anywhere else. Star columns with a MaxWidth answer both, because the cap is what makes "share the width" mean the right thing at each end. Wide, the three numeric columns stop growing at what their text needs and NAME keeps every remaining pixel. Narrow, nothing carries a MinWidth to overflow with, so all four give ground together and NAME — weighted heaviest — is the last to run out. MODIFIED takes the extra weight so it reaches its cap first, being the widest content and the column most often actually read; the local pane's NAME carries the remote's PERMS weight folded into it, which is what makes SIZE and MODIFIED come out the same width on both sides of the arrow column. Timestamps.Format already argued that both panes write a time the same way so the two can be read against each other, and two different widths would have made that argument for nothing. ◆ THE HEADINGS RAN TOGETHER, and that was visible as one word: SIZE ended on the pixel MODIFIED began at, so the row read "SIZEMODIFIED". They are right-aligned in their own columns, so the gap has to come from a left margin on each — which does not move the label and does stop the column before it reaching this one. The three now carry one, and ellipsize rather than clip where even the label has no room. ◆ TWO PLACEHOLDERS WERE CUT OFF MID-WORD, which reads as a rendering fault rather than as a hint. MKDIR's box drew "new directo" — 101 pixels of text in 74 pixels of room — and says "directory" now, since the button beside it carries the "new" half already. The pane header's path box drew a path ending mid-segment at the narrow budget and says "path": the only time that placeholder shows is on a pane with nothing connected, where the box is disabled and the invitation below is doing the explaining, and what the box is for is in its tooltip where there is room for it. FOUR COPIES OF THE COLUMN DEFINITIONS, one heading row and one row template per pane. Avalonia cannot share a ColumnDefinitions instance between two Grids — each mutates its own computed sizes — and SharedSizeGroup only applies to Auto columns, so what catches a copy that drifts is measurement rather than discipline: every cell is held against the width its own text needs when unconstrained, the headings against each other, and NAME against zero at the narrowest budget. Nothing asserts a number this file also wrote down, which is the failure mode a test of a layout most easily has. The roomy end is measured at the width a maximised 1843-pixel window leaves, which is where this was reported from; LayoutHarness.SessionScreenWidth cannot express it because that constant is pinned to the window's minimum, so the arithmetic is spelled out beside the test that uses it.
This commit is contained in:
1 parent
882f01c515
commit
b2f93a172b
2 files changed
+350
-13
No files matched your search
@@ -33,6 +33,43 @@
|
||||
layer has not got. See docs/design-import-gaps.md.
|
||||
-->
|
||||
|
||||
<!--
|
||||
══ THE TWO LISTINGS' COLUMNS ═════════════════════════════════════════════════════════════════════════
|
||||
◆ They were fixed pixel widths, and fixed was wrong at both ends of the range this screen actually gets.
|
||||
|
||||
The numbers — 20/*/60/56 here and 20/*/56/52/48 across the arrow column — were chosen against the 204
|
||||
pixels the session shell's own QUICK ACCESS sidebar leaves a pane at the window's minimum. Measured,
|
||||
they were wrong in both directions at once:
|
||||
|
||||
· MODIFIED prints "2026-08-21 11:36", which needs 116 pixels, and never had more than 48. So the
|
||||
column was truncated at every width this screen has ever been drawn at — a maximised window showed
|
||||
"2026-08" beside a NAME column with four hundred empty pixels in it. PERMS needs 60 for a
|
||||
ten-character mode and had 48; SIZE needs 58 for "999.9 GB" and had 56.
|
||||
· At 204 the remote pane's NAME column measured **zero pixels wide**. Twenty for the glyph plus
|
||||
56+52+48 for the numbers is 176 of the 180 a row has, so the file names — the one column a file
|
||||
browser exists to show — were not drawn at all.
|
||||
|
||||
Star columns with a MaxWidth fix both, because the cap is what makes "share the width" mean the right
|
||||
thing at each end. Wide, the three numeric columns stop growing at what their own text needs and NAME
|
||||
keeps every remaining pixel. Narrow, nothing has a MinWidth to overflow with, so all four give ground
|
||||
together and NAME — weighted heaviest — keeps enough to read a name by.
|
||||
|
||||
MODIFIED carries the extra weight (1.6) so that it reaches its cap first: it is the widest content and
|
||||
the column somebody is most often actually reading. The local pane's NAME is 3* against the remote's 2*,
|
||||
which is the remote's PERMS weight folded into it — that is what makes SIZE and MODIFIED come out the
|
||||
same width on both sides of the arrow column, so the same amount of a timestamp is visible in each. See
|
||||
Timestamps.Format for why both panes write one the same way in the first place; a shared format read at
|
||||
two different widths would have made that argument for nothing.
|
||||
|
||||
◆ FOUR COPIES OF THIS, and they have to stay in step: a heading row and a row template per pane. Avalonia
|
||||
cannot share one ColumnDefinitions instance between two Grids — each mutates its own computed sizes —
|
||||
and SharedSizeGroup only applies to Auto columns. What catches a copy that drifts is measurement rather
|
||||
than discipline: ScreenLayoutTests holds every cell against the width its own text needs
|
||||
(TheListingColumnsShowTheirContentInFullWhenThereIsRoom), the headings against each other
|
||||
(TheListingHeadingsDoNotRunIntoEachOther), and NAME against zero at the narrowest budget
|
||||
(TheNameColumnSurvivesTheNarrowestBudget).
|
||||
-->
|
||||
|
||||
<UserControl.Styles>
|
||||
<!--
|
||||
── v5b ─────────────────────────────────────────────────────────────────────────────────────────────
|
||||
@@ -259,10 +296,18 @@
|
||||
the row template below for why the whole column set was chosen against 204 pixels rather than the
|
||||
design's own 1920-pixel canvas.
|
||||
-->
|
||||
<Grid Grid.Row="2" ColumnDefinitions="20,*,60,56" Margin="0,2,10,4">
|
||||
<Grid Grid.Row="2" Margin="0,2,10,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="20" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="*" MaxWidth="66" />
|
||||
<ColumnDefinition Width="1.6*" MaxWidth="124" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="1" Classes="label" Text="NAME" FontSize="9.5" Margin="8,0,8,0" />
|
||||
<TextBlock Grid.Column="2" Classes="label" Text="SIZE" FontSize="9.5" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Column="3" Classes="label" Text="MODIFIED" FontSize="9.5" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Column="2" Classes="label" Text="SIZE" FontSize="9.5" Margin="8,0,0,0"
|
||||
HorizontalAlignment="Right" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="3" Classes="label" Text="MODIFIED" FontSize="9.5" Margin="8,0,0,0"
|
||||
HorizontalAlignment="Right" TextTrimming="CharacterEllipsis" />
|
||||
</Grid>
|
||||
|
||||
<!--
|
||||
@@ -274,13 +319,19 @@
|
||||
SelectedItem="{Binding SelectedLocalEntry}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:LocalEntryRowViewModel">
|
||||
<Grid ColumnDefinitions="20,*,60,56" Height="38" Margin="14,0,10,0">
|
||||
<Grid Height="38" Margin="14,0,10,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="20" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="*" MaxWidth="66" />
|
||||
<ColumnDefinition Width="1.6*" MaxWidth="124" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Classes="entryicon" Text="{Binding IconGlyph}" />
|
||||
<TextBlock Grid.Column="1" Classes="mono entry" Classes.dir="{Binding IsNavigable}"
|
||||
Text="{Binding Name}" FontSize="13.5"
|
||||
Margin="10,0,8,0" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="2" Classes="mono entrysize" Text="{Binding Size}" FontSize="12"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
Margin="8,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Classes="mono entrydate" Text="{Binding Modified}" FontSize="12"
|
||||
Margin="8,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
@@ -374,8 +425,14 @@
|
||||
</StackPanel>
|
||||
<TextBox Grid.Column="1" Classes="pathbox" VerticalAlignment="Center"
|
||||
Text="{Binding RemotePathDraft}" IsEnabled="{Binding IsConnected}"
|
||||
PlaceholderText="/path/to/somewhere"
|
||||
PlaceholderText="path"
|
||||
ToolTip.Tip="Type a path and press Enter. A relative path is taken from here; ~ is the account's home directory.">
|
||||
<!--
|
||||
One word, because the only time this placeholder shows is on a pane with nothing connected,
|
||||
where the box is disabled and the invitation below is doing the explaining. "/path/to/
|
||||
somewhere" needs 146 pixels and had 91 at the session shell's narrowest, so it drew as a
|
||||
path cut off mid-segment. What the box is for is in the tooltip, where there is room for it.
|
||||
-->
|
||||
<TextBox.KeyBindings>
|
||||
<KeyBinding Gesture="Enter" Command="{Binding GoToTypedRemotePathCommand}" />
|
||||
<KeyBinding Gesture="Escape" Command="{Binding RevertTypedRemotePathCommand}" />
|
||||
@@ -584,10 +641,16 @@
|
||||
is showing, 140 plus MKDIR plus the spacing between them ran past the pane's own edge. Still wide
|
||||
enough for a real directory name to be typed and read back, which is what this box is for; a
|
||||
name that outgrows it scrolls inside the box the way every TextBox already does.
|
||||
|
||||
◆ The placeholder says "directory" rather than "new directory", which is what it said until it
|
||||
was measured: the longer text needs 101 pixels inside a box that has 74, so it drew as "new
|
||||
directo" — a placeholder cut off mid-word, which reads as a rendering fault rather than as a
|
||||
hint. MKDIR is right beside it and carries the "new" half already. The path box in the header
|
||||
above lost the same argument and for the same reason; see its own PlaceholderText.
|
||||
-->
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="6"
|
||||
IsVisible="{Binding IsConnected}">
|
||||
<TextBox Width="90" Text="{Binding NewRemoteFolder}" PlaceholderText="new directory" />
|
||||
<TextBox Width="90" Text="{Binding NewRemoteFolder}" PlaceholderText="directory" />
|
||||
<Button Classes="ghost" Content="MKDIR" Command="{Binding CreateRemoteFolderCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
@@ -597,25 +660,42 @@
|
||||
48 pixels rather than the drawer's own wider habit, and SIZE/MODIFIED shrink to match the local
|
||||
pane's narrower numbers. See the local pane's own remark on why 204 rather than the design's 1920.
|
||||
-->
|
||||
<Grid Grid.Row="5" ColumnDefinitions="20,*,56,52,48" Margin="0,2,10,4">
|
||||
<Grid Grid.Row="5" Margin="0,2,10,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="20" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="*" MaxWidth="66" />
|
||||
<ColumnDefinition Width="1.6*" MaxWidth="124" />
|
||||
<ColumnDefinition Width="*" MaxWidth="66" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="1" Classes="label" Text="NAME" FontSize="9.5" Margin="8,0,8,0" />
|
||||
<TextBlock Grid.Column="2" Classes="label" Text="SIZE" FontSize="9.5" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Column="3" Classes="label" Text="MODIFIED" FontSize="9.5" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Column="4" Classes="label" Text="PERMS" FontSize="9.5" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Column="2" Classes="label" Text="SIZE" FontSize="9.5" Margin="8,0,0,0"
|
||||
HorizontalAlignment="Right" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="3" Classes="label" Text="MODIFIED" FontSize="9.5" Margin="8,0,0,0"
|
||||
HorizontalAlignment="Right" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="4" Classes="label" Text="PERMS" FontSize="9.5" Margin="6,0,0,0"
|
||||
HorizontalAlignment="Right" TextTrimming="CharacterEllipsis" />
|
||||
</Grid>
|
||||
|
||||
<ListBox Grid.Row="6" x:Name="RemoteList" Classes="filerows" ItemsSource="{Binding RemoteEntries}"
|
||||
SelectedItem="{Binding SelectedRemoteEntry}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:RemoteEntryRowViewModel">
|
||||
<Grid ColumnDefinitions="20,*,56,52,48" Height="38" Margin="14,0,10,0">
|
||||
<Grid Height="38" Margin="14,0,10,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="20" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="*" MaxWidth="66" />
|
||||
<ColumnDefinition Width="1.6*" MaxWidth="124" />
|
||||
<ColumnDefinition Width="*" MaxWidth="66" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Classes="entryicon" Text="{Binding IconGlyph}" />
|
||||
<TextBlock Grid.Column="1" Classes="mono entry" Classes.dir="{Binding IsNavigable}"
|
||||
Classes.exec="{Binding IsExecutable}"
|
||||
Text="{Binding Name}" FontSize="13.5"
|
||||
Margin="10,0,8,0" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="2" Classes="mono entrysize" Text="{Binding Size}" FontSize="12"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
Margin="8,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Classes="mono entrydate" Text="{Binding Modified}" FontSize="12"
|
||||
Margin="8,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="4" Classes="mono perms" Classes.loose="{Binding IsWorldWritable}"
|
||||
|
||||
Reference in new issue
Block a user