Rework the depot browser layout and confirm a crewless start

The vehicle database panel loses its header bar and packs the search box and
the archival filter into one line, the class combo takes a full-width line of
its own with a miniature (big in the drop-down, one line when closed) and the
bulk / texture-base actions move into the Add button's drop-down. The mini
preview sits beside the texture data and stays hidden until an entry is
picked, so the list keeps the space.

Picking a class or a vehicle now fills both combos in, and a class alone is a
valid filter (it used to leave the list empty without a category). The combos
and the list are rebuilt on the next dispatcher pass, since clearing Items
from inside the SelectionChanged that asked for it throws.

Vehicle removal becomes a per-card tool next to flip / crew, the scenery and
vehicle names move into their panel headers, and the texture randomizer
dialog sizes to its content instead of clipping its last button.

Start no longer hides behind Ctrl: a consist with no crew and no passenger
says so on the button and asks for confirmation before launching.
This commit is contained in:
maj00r
2026-08-25 20:58:25 +02:00
parent a93af4bd44
commit 9e2166065b
8 changed files with 347 additions and 194 deletions

View File

@@ -13,97 +13,106 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<!-- Consists list and the brakes/loads editor share the upper area
evenly, so the editor has room for all its controls. -->
<!-- Consists list and the brakes/loads editor share the upper area,
the editor taking a bit more of it. -->
<RowDefinition Height="*" />
<RowDefinition Height="*" MinHeight="210" />
<RowDefinition Height="1.25*" MinHeight="250" />
<RowDefinition Height="190" />
</Grid.RowDefinitions>
<!-- Vehicle database browser (left, rows 0-1) -->
<HeaderedContentControl Grid.RowSpan="2" Theme="{StaticResource GroupBox}"
Header="{Binding [VehicleDatabase], Source={x:Static starterNg:App.Loc}}">
<Border Grid.RowSpan="2" Background="{StaticResource CarbonPanelBg}"
BorderBrush="{StaticResource CarbonBorderLight}" BorderThickness="1"
CornerRadius="2" Padding="8">
<DockPanel LastChildFill="True">
<Button Name="textureBaseButton" DockPanel.Dock="Top" Classes="Basic" FontSize="11"
Margin="0,0,0,6" Padding="8,2" Cursor="Hand"
HorizontalAlignment="Left"
Click="TextureBaseButton_OnClick"
Content="{Binding [OpenTextureBase], Source={x:Static starterNg:App.Loc}}" />
<Grid DockPanel.Dock="Top" ColumnDefinitions="*,*" ColumnSpacing="6" Margin="0,0,0,6">
<ComboBox Name="categoryCombo" Grid.Column="0" HorizontalAlignment="Stretch"
<DockPanel DockPanel.Dock="Top" Margin="0,0,0,6" LastChildFill="True">
<CheckBox Name="hideArchivalCheck" DockPanel.Dock="Right" FontSize="11"
VerticalAlignment="Center" Margin="8,0,0,0"
Content="{Binding [HideArchivalVehicles], Source={x:Static starterNg:App.Loc}}"
IsCheckedChanged="HideArchivalCheck_OnChanged" />
<TextBox Name="searchBox" VerticalAlignment="Center"
Watermark="{Binding [Search], Source={x:Static starterNg:App.Loc}}"
TextChanged="SearchBox_OnTextChanged" />
</DockPanel>
<Grid DockPanel.Dock="Top" RowDefinitions="Auto,Auto" RowSpacing="6" Margin="0,0,0,6">
<ComboBox Name="categoryCombo" Grid.Row="0" HorizontalAlignment="Stretch"
PlaceholderText="{Binding [Category], Source={x:Static starterNg:App.Loc}}"
PointerWheelChanged="Combo_OnPointerWheel"
SelectionChanged="CategoryCombo_OnSelectionChanged" />
<ComboBox Name="classCombo" Grid.Column="1" HorizontalAlignment="Stretch"
<ComboBox Name="classCombo" Grid.Row="1" HorizontalAlignment="Stretch"
PlaceholderText="{Binding [Class], Source={x:Static starterNg:App.Loc}}"
PointerWheelChanged="Combo_OnPointerWheel"
SelectionChanged="ClassCombo_OnSelectionChanged" />
</Grid>
<TextBox Name="searchBox" DockPanel.Dock="Top" Margin="0,0,0,6"
Watermark="{Binding [Search], Source={x:Static starterNg:App.Loc}}"
TextChanged="SearchBox_OnTextChanged" />
<CheckBox Name="hideArchivalCheck" DockPanel.Dock="Top" Margin="0,0,0,8"
Content="{Binding [HideArchivalVehicles], Source={x:Static starterNg:App.Loc}}"
IsCheckedChanged="HideArchivalCheck_OnChanged" />
<!-- Mini preview of the selected entry + the single Add button.
Both are docked at the bottom, under the flat vehicle list. -->
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Spacing="4" Margin="0,4,0,0">
<Button Name="addAllCategoryButton" Classes="Flat" FontSize="11" Padding="6,2"
Cursor="Hand" Click="AddAllCategoryButton_OnClick"
Content="{Binding [AddAllCategory], Source={x:Static starterNg:App.Loc}}"
ToolTip.Tip="{Binding [TipAddAllCategory], Source={x:Static starterNg:App.Loc}}" />
<Button Name="addUniqueMmdButton" Classes="Flat" FontSize="11" Padding="6,2"
Cursor="Hand" Click="AddUniqueMmdButton_OnClick"
Content="{Binding [AddUniqueMmd], Source={x:Static starterNg:App.Loc}}"
ToolTip.Tip="{Binding [TipAddUniqueMmd], Source={x:Static starterNg:App.Loc}}" />
</StackPanel>
<Button Name="addVehicleButton" DockPanel.Dock="Bottom" Classes="Flat Accent"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
Margin="0,8,0,0" IsEnabled="False" Cursor="Hand"
Click="AddVehicleButton_OnClick"
Content="{Binding [AddVehicle], Source={x:Static starterNg:App.Loc}}" />
<Border Name="miniPreviewPanel" DockPanel.Dock="Bottom" Height="62" Margin="0,6,0,0"
Background="{StaticResource CarbonInputBg}"
BorderBrush="{StaticResource CarbonBorderLight}" BorderThickness="1"
CornerRadius="2" Cursor="Hand"
PointerPressed="MiniPreview_OnPointerPressed">
<Image Name="miniPreview" Stretch="Uniform" Margin="6" />
</Border>
<StackPanel Name="textureInfoPanel" DockPanel.Dock="Bottom" Margin="0,4,0,0" Spacing="1" />
<!-- The arrow stays enabled with nothing selected - adding a whole
category needs no highlighted entry. -->
<DockPanel DockPanel.Dock="Bottom" Margin="0,8,0,0">
<Button Name="addMoreButton" DockPanel.Dock="Right" Classes="Flat Accent"
Width="28" Margin="4,0,0,0" Cursor="Hand" Content="&#x25BE;"
HorizontalContentAlignment="Center"
ToolTip.Tip="{Binding [AddAllCategory], Source={x:Static starterNg:App.Loc}}">
<Button.Flyout>
<MenuFlyout Placement="TopEdgeAlignedRight">
<MenuItem Click="AddAllCategoryButton_OnClick"
Header="{Binding [AddAllCategory], Source={x:Static starterNg:App.Loc}}"
ToolTip.Tip="{Binding [TipAddAllCategory], Source={x:Static starterNg:App.Loc}}" />
<MenuItem Click="AddUniqueMmdButton_OnClick"
Header="{Binding [AddUniqueMmd], Source={x:Static starterNg:App.Loc}}"
ToolTip.Tip="{Binding [TipAddUniqueMmd], Source={x:Static starterNg:App.Loc}}" />
<Separator />
<MenuItem Click="TextureBaseButton_OnClick"
Header="{Binding [OpenTextureBase], Source={x:Static starterNg:App.Loc}}" />
</MenuFlyout>
</Button.Flyout>
</Button>
<Button Name="addVehicleButton" Classes="Flat Accent"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
IsEnabled="False" Cursor="Hand"
Click="AddVehicleButton_OnClick"
Content="{Binding [AddVehicle], Source={x:Static starterNg:App.Loc}}" />
</DockPanel>
<Grid Name="browserDetails" DockPanel.Dock="Bottom" ColumnDefinitions="130,*"
ColumnSpacing="6" Margin="0,6,0,0" IsVisible="False">
<Border Name="miniPreviewPanel" Grid.Column="0" Height="66"
VerticalAlignment="Top"
Background="{StaticResource CarbonInputBg}"
BorderBrush="{StaticResource CarbonBorderLight}" BorderThickness="1"
CornerRadius="2" Cursor="Hand"
PointerPressed="MiniPreview_OnPointerPressed">
<Image Name="miniPreview" Stretch="Uniform" Margin="6" />
</Border>
<StackPanel Name="textureInfoPanel" Grid.Column="1" Spacing="1"
VerticalAlignment="Center" />
</Grid>
<!-- Flat list of vehicle entries (plain text, no expanders).
Selecting one shows its mini and enables Add; double-click
replaces the selected consist vehicle. -->
<ListBox Name="vehicleListBox" Classes="Compact"
<ListBox Name="vehicleListBox" Classes="Compact" MinHeight="120"
SelectionChanged="VehicleListBox_OnSelectionChanged"
DoubleTapped="VehicleListBox_OnDoubleTapped"
PointerPressed="VehicleListBox_OnPointerPressed" />
</DockPanel>
</HeaderedContentControl>
</Border>
<!-- Consists present on the scenery selected in the Scenarios tab.
Selecting one loads it into the editor below. -->
<HeaderedContentControl Grid.Column="1" Grid.Row="0" Theme="{StaticResource GroupBox}"
Header="{Binding [MapConsists], Source={x:Static starterNg:App.Loc}}">
Selecting one loads it into the editor below; the header carries the
scenery name (see PopulateSceneryConsists). -->
<HeaderedContentControl Name="mapConsistsPanel" Grid.Column="1" Grid.Row="0"
Theme="{StaticResource GroupBox}">
<DockPanel LastChildFill="True">
<TextBlock Name="mapSceneryLabel" DockPanel.Dock="Top" FontSize="12"
Opacity="0.8" Margin="0,0,0,6" TextTrimming="CharacterEllipsis" />
<ListBox Name="sceneryConsistList" Classes="Compact"
SelectionChanged="SceneryConsistList_OnSelectionChanged"
KeyDown="SceneryConsistList_OnKeyDown" />
</DockPanel>
</HeaderedContentControl>
<!-- Brakes / Loads editor (middle-right) -->
<HeaderedContentControl Grid.Column="1" Grid.Row="1" Theme="{StaticResource GroupBox}"
Header="{Binding [SelectedVehicle], Source={x:Static starterNg:App.Loc}}">
<!-- Brakes / Loads editor (middle-right). Header carries the vehicle
name (see UpdateDetails). -->
<HeaderedContentControl Name="selectedVehiclePanel" Grid.Column="1" Grid.Row="1"
Theme="{StaticResource GroupBox}">
<DockPanel LastChildFill="True">
<Button Name="removeVehicleButton" DockPanel.Dock="Bottom" Classes="Flat"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
Margin="0,8,0,0" IsEnabled="False" Cursor="Hand"
Click="RemoveVehicleButton_OnClick"
Content="{Binding [RemoveSelectedVehicle], Source={x:Static starterNg:App.Loc}}" />
<TabControl>
<TabItem Header="{Binding [Brakes], Source={x:Static starterNg:App.Loc}}">
<ScrollViewer VerticalScrollBarVisibility="Auto">