Public Access
Open a group by double-clicking it, and say where you are
ONE PRESS WAS DOING TWO JOBS. A group card was the only place a group could be selected — it is what EDIT and DELETE aim at — and it was also the control that narrowed the grid to that group. So there was no way to name a group in order to rename it without every host outside it leaving the screen at the same moment, and no way back except a SHOW ALL button that appeared beside the heading. Two gestures instead. A click selects and does nothing else; a double-click opens, which is what the host cards below already do to get a shell and what the transfers screen's directories already do to go inside one. The grid now has one vocabulary rather than one per list. The gesture is wired in the code-behind beside the host one, and guarded the same way: a double-click on the space around the cards must not open whichever group happened to be selected. THE CARDS ARE ONE LEVEL NOW, not every group in the keychain. Groups nest, and drawing all of them flat was the only honest thing to do while a card was a filter — a filter nobody can see is a filter nobody can turn off. Once opening one became navigation the cards became its contents, and VisibleGroups is that level beside Groups the way VisibleHosts sits beside Hosts. Groups itself is untouched: it is what every lookup reads and what the phone's headings are built from, and the phone binds none of the new members. Which is what the trail is for. A level with no name and no way out is a grid that has quietly hidden things, so a breadcrumb sits above the cards — drawn exactly as the transfers screen draws a directory path, same flat crumbs and same separator, because it is the same control answering the same question and a window with two breadcrumbs that look different has two ideas of what a path is. The first crumb is always there and always goes back to every host, which is what SHOW ALL was; that button went with it, because a control that only says "stop" beside a trail that says where you are is a second control for one job, and this one also gets you back one level rather than all the way. EDIT AND DELETE AIM AT GroupTarget: the selected card, or the open group when no card is selected. Without the fallback a group with nothing inside it could be opened and then never edited, because opening a group is exactly what takes its own card off the screen. It is also what a file manager does — act on the selection, and on the current folder when there is none — and the pair is now hidden with nothing to act on rather than shown doing nothing. A DANGLING PARENT AND A CYCLE BOTH HAD TO END UP SOMEWHERE REACHABLE. Neither is prevented: a parent id may point at a group deleted on another machine, and two clients can each re-parent A under B and B under A while offline, which no merge can see because the pointer is inside the payload. EffectiveParents promotes both to the outermost level, which is the same degradation the resolver's visited set produces for inheritance. The repair for either is the group's own editor and the editor is opened from its card, so a group drawn nowhere would be a broken state with the fix locked inside it. Three tests in HostGridTests: the split rule through the properties the cards bind, the pointer gesture itself in two windows so that "one press still only selects" is asserted separately from the pair, and a nested group opened, emptied of cards and walked back out of one level. The last presses the trail as it is actually rendered rather than calling the command, because a crumb reaches the vault through a $parent binding — a string that compiles whether or not it resolves, and would otherwise leave a row of buttons that do nothing. 85 layout tests and 234 shell-flow tests pass. Manual-checks 3.2, 7.6 and 7.7 follow the new gestures, and 3.2a and 3.4a are new: nesting, and the two states above, both of which need two machines and neither of which headless Avalonia can reach.
This commit is contained in:
@@ -177,15 +177,13 @@
|
||||
|
||||
<!--
|
||||
The group's own two actions, beside the group cards rather than in the toolbar, because they
|
||||
act on the selected card and this is where the selection is made. Hidden rather than
|
||||
disabled while DELETE's question is up, as every other pair in this application is, so it
|
||||
cannot be pressed twice — see VaultViewModel.ShowsGroupActions.
|
||||
act on the card that is selected — and this is where the selection is made. Hidden rather
|
||||
than disabled while DELETE's question is up, as every other pair in this application is, so
|
||||
it cannot be pressed twice, and hidden again when there is nothing for them to act on. What
|
||||
that is, with no card selected, is the group the trail below ends with; see
|
||||
VaultViewModel.GroupTarget.
|
||||
-->
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="6">
|
||||
<Button Classes="ghost" Content="SHOW ALL"
|
||||
Command="{Binding ClearGroupFilterCommand}"
|
||||
IsVisible="{Binding IsFilteredByGroup}"
|
||||
ToolTip.Tip="Stops narrowing the grid to one group." />
|
||||
<Button Classes="ghost" Content="EDIT" Command="{Binding EditGroupCommand}"
|
||||
IsVisible="{Binding ShowsGroupActions}" />
|
||||
<Button Classes="ghost" Content="DELETE" Command="{Binding DeleteGroupCommand}"
|
||||
@@ -193,6 +191,43 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!--
|
||||
============ WHERE YOU ARE ============
|
||||
The trail, drawn exactly as the transfers screen draws a directory path, because it is the same
|
||||
control answering the same question — and a window with two breadcrumbs that look different has
|
||||
two ideas of what a path is. See TransfersScreen.axaml.
|
||||
|
||||
It exists because the cards below are one level of a tree rather than every group at once, and
|
||||
a level nobody can name is a grid that has quietly hidden things. The first crumb is always
|
||||
there and always goes back to every host, which is what the SHOW ALL button used to be: a
|
||||
button that only says "stop" beside a trail that says where you are is the second control for
|
||||
the same job, and this one also gets you halfway back rather than all the way.
|
||||
-->
|
||||
<ItemsControl ItemsSource="{Binding GroupTrail}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate><WrapPanel Orientation="Horizontal" /></ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:GroupCrumbViewModel">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<!--
|
||||
The command is the vault's and the item is a crumb, so it is reached through the
|
||||
ItemsControl's data context — the same way every other templated command on the
|
||||
desktop is bound.
|
||||
-->
|
||||
<Button Classes="flat" Padding="3,1"
|
||||
Command="{Binding $parent[ItemsControl].((vm:VaultViewModel)DataContext).OpenGroupCommand}"
|
||||
CommandParameter="{Binding Group}">
|
||||
<TextBlock Classes="mono" Text="{Binding Name}" FontSize="11"
|
||||
Foreground="{StaticResource TextDim}" />
|
||||
</Button>
|
||||
<TextBlock Classes="mono" Text="›" FontSize="11"
|
||||
Foreground="{StaticResource TextFaint}" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<Border Padding="10" Background="{StaticResource DangerWash}" CornerRadius="6"
|
||||
IsVisible="{Binding IsConfirmingGroupDeletion}">
|
||||
<views:ConfirmDeleteCard />
|
||||
@@ -204,21 +239,28 @@
|
||||
every other list in this application draws a selected row. Buttons would have needed a
|
||||
Classes.active binding per card and a second copy of "which one".
|
||||
|
||||
SelectedItem is GroupFilter and not SelectedGroup. The two are nearly the same thing here —
|
||||
GroupFilter assigns SelectedGroup — but only one of them may narrow the grid; see the property
|
||||
for why the phone's own use of SelectedGroup must not.
|
||||
◆ ONE CLICK SELECTS, TWO OPEN. SelectedItem is the selection and nothing else now — the
|
||||
gesture that opens a group is a double-click, wired in the code-behind beside the one that
|
||||
opens a shell on a host. One click used to mean both, and a card was then the only place a
|
||||
group could be named while also being the control that threw the rest of the grid away.
|
||||
|
||||
◆ THIS IS ONE LEVEL, NOT EVERY GROUP. It binds VisibleGroups: what is inside the group the
|
||||
trail above ends with, or the outermost groups when it ends at ALL HOSTS. Folded away entirely
|
||||
at a group with nothing inside it, which is an ordinary thing to open — the trail and the two
|
||||
buttons stay, because leaving it is a gesture and editing it is a button.
|
||||
|
||||
◆ THESE CARDS ARE THE DROP TARGET. A host card dragged onto one is filed under that group, and
|
||||
that is the whole of what a drag does on this screen. It used to be a heading inside the host
|
||||
grid, and the headings are gone — see the note on the host grid below. A group is a thing that
|
||||
is drawn once, at the top, where the eye already goes to narrow the grid; a target that is also
|
||||
the label of what you are aiming at needs no explaining. See the code-behind for the gesture.
|
||||
is drawn once, at the top, where the eye already goes; a target that is also the label of what
|
||||
you are aiming at needs no explaining. See the code-behind for the gesture.
|
||||
-->
|
||||
<ListBox Classes="tiles" x:Name="GroupGrid"
|
||||
DragDrop.AllowDrop="True"
|
||||
ItemsSource="{Binding Groups}"
|
||||
SelectedItem="{Binding GroupFilter}"
|
||||
ToolTip.Tip="Press a group to show only its hosts. Drag a host card onto one to file it there.">
|
||||
IsVisible="{Binding HasVisibleGroups}"
|
||||
ItemsSource="{Binding VisibleGroups}"
|
||||
SelectedItem="{Binding SelectedGroup}"
|
||||
ToolTip.Tip="Press a group to select it, double-press to open it. Drag a host card onto one to file it there.">
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate><WrapPanel /></ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
|
||||
Reference in New Issue
Block a user