335 lines
17 KiB
XML
335 lines
17 KiB
XML
<Window xmlns="https://github.com/avaloniaui"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:vm="using:NexvaneHub.ViewModels"
|
|
xmlns:conv="using:NexvaneHub.Converters"
|
|
xmlns:avc="using:Avalonia.Data.Converters"
|
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
mc:Ignorable="d"
|
|
x:Class="NexvaneHub.Views.MainWindow"
|
|
x:DataType="vm:MainWindowViewModel"
|
|
Title="Nexvane Hub"
|
|
Width="1180" Height="740"
|
|
MinWidth="920" MinHeight="600"
|
|
ExtendClientAreaToDecorationsHint="True"
|
|
ExtendClientAreaChromeHints="NoChrome"
|
|
ExtendClientAreaTitleBarHeightHint="62">
|
|
|
|
<Design.DataContext>
|
|
<vm:MainWindowViewModel />
|
|
</Design.DataContext>
|
|
|
|
<Grid RowDefinitions="62,*">
|
|
|
|
<!-- ===== Title bar (fully custom - see MainWindow.axaml.cs for the
|
|
drag/minimize/maximize/close handlers this wires up to) ===== -->
|
|
<Border Grid.Row="0" Classes="topBar" PointerPressed="TitleBar_PointerPressed">
|
|
<Grid ColumnDefinitions="Auto,*">
|
|
|
|
<!-- Logo spans the full height of both rows below, flush in the
|
|
top-left corner (like the editor's), not confined to the
|
|
title row alone. Vector geometry lifted straight from the
|
|
provided nexvane-logo.svg - see Assets/nexvane-logo.svg for
|
|
the source. Coordinates have the SVG's scale/translate baked
|
|
in directly (computed offline) rather than applied via
|
|
RenderTransform, so there's no Viewbox+transform reconciliation
|
|
for anything to get wrong - what's below is the tight bounding
|
|
box of the mark itself, plus a small safety margin. Sized to
|
|
fill most of its column's height (Border.topBar's padding trims
|
|
a few px off each end) rather than floating small in the
|
|
middle, so the text rows don't visually overshoot the mark. -->
|
|
<Border Grid.Column="0" Classes="logoBadge">
|
|
<Viewbox Width="36" Height="40" Stretch="Uniform" HorizontalAlignment="Right" VerticalAlignment="Center">
|
|
<Canvas Width="835.96" Height="934.96">
|
|
<Path Fill="White" Data="M 17.980,100.680 L 17.980,183.480 L 100.480,100.980 C 145.880,55.580 182.980,18.380 182.980,18.280 C 182.980,18.080 145.880,17.980 100.480,17.980 L 17.980,17.980 L 17.980,100.680" />
|
|
<Path Fill="White" Data="M 719.680,114.780 L 622.980,211.480 L 622.980,343.780 C 622.980,476.680 623.380,503.480 626.980,584.380 C 628.080,608.580 628.780,628.580 628.580,628.780 C 627.880,629.380 648.480,664.780 369.180,182.980 C 334.280,122.780 304.180,70.880 302.180,67.580 L 298.680,61.780 L 158.380,202.080 L 17.980,342.480 L 17.980,624.480 L 17.980,906.480 L 114.980,809.480 L 211.980,712.480 L 211.980,585.980 C 211.980,516.380 211.480,447.580 210.980,432.980 C 209.780,401.480 207.380,351.080 205.580,320.480 C 204.780,308.380 204.380,298.380 204.480,298.180 C 204.880,297.680 199.980,289.280 365.980,577.980 C 452.480,728.380 524.980,854.580 527.180,858.380 L 531.180,865.280 L 674.580,721.880 L 817.980,578.480 L 817.980,298.280 C 817.980,144.080 817.680,17.980 817.180,17.980 C 816.780,17.980 772.980,61.480 719.680,114.780" />
|
|
<Path Fill="White" Data="M 727.480,826.980 L 637.480,916.980 L 727.780,916.980 L 817.980,916.980 L 817.980,826.980 C 817.980,777.480 817.880,736.980 817.680,736.980 C 817.580,736.980 776.980,777.480 727.480,826.980" />
|
|
</Canvas>
|
|
</Viewbox>
|
|
</Border>
|
|
|
|
<StackPanel Grid.Column="1" Margin="20,0,20,0">
|
|
<Grid Height="34" ColumnDefinitions="*,Auto">
|
|
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center">
|
|
<TextBlock Classes="appTitle" Text="Nexvane" />
|
|
<TextBlock Classes="appTitleMuted" Text="Hub" />
|
|
</StackPanel>
|
|
|
|
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center" Spacing="0">
|
|
<Button Classes="iconButton" Content="⚙" ToolTip.Tip="Settings" Margin="0,0,8,0" />
|
|
<Button Classes="captionButton" Content="—" Click="MinimizeButton_Click" ToolTip.Tip="Minimize" />
|
|
<Button Classes="captionButton" Content="□" Click="MaximizeButton_Click" ToolTip.Tip="Maximize" />
|
|
<Button Classes="captionButton captionButtonClose" Content="✕" Click="CloseButton_Click" ToolTip.Tip="Close" />
|
|
</StackPanel>
|
|
</Grid>
|
|
|
|
<!-- Menu row sits below the title, not above it. Fixed height
|
|
(34 + 22 = 56, plus Border.topBar's 3px top/bottom padding =
|
|
62 total) rather than auto-sized from padding/margin, so the
|
|
bar's total height is a known number instead of something
|
|
several nested layers of content have to happen to agree on.
|
|
Both rows hug their content tightly rather than centering
|
|
inside oversized fixed heights, and the shared 3px padding on
|
|
Border.topBar keeps everything off the bar's very top/bottom
|
|
edges. Each item opens a dropdown via Button.Flyout - Avalonia
|
|
handles positioning, click-away-to-close, and Escape for us;
|
|
the content inside is ours. Margin.Left is negative to cancel
|
|
out Button.menuBarItem's own 6px left padding - otherwise
|
|
"File"'s text sits right of where "Nexvane" starts, since the
|
|
title TextBlock has no padding of its own to match against. -->
|
|
<StackPanel Orientation="Horizontal" Height="22" VerticalAlignment="Top" Spacing="12" Margin="-6,0,0,0">
|
|
|
|
<Button Classes="menuBarItem" Content="File">
|
|
<Button.Flyout>
|
|
<Flyout Placement="Bottom">
|
|
<StackPanel MinWidth="190">
|
|
<Button Classes="dropdownItem" Content="New Project" />
|
|
<Button Classes="dropdownItem" Content="Open Project" />
|
|
<Border Classes="dropdownSeparator" />
|
|
<Button Classes="dropdownItem" Content="Save" />
|
|
<Button Classes="dropdownItem" Content="Save As..." />
|
|
<Border Classes="dropdownSeparator" />
|
|
<Button Classes="dropdownItem" Content="Exit" />
|
|
</StackPanel>
|
|
</Flyout>
|
|
</Button.Flyout>
|
|
</Button>
|
|
|
|
<Button Classes="menuBarItem" Content="Edit">
|
|
<Button.Flyout>
|
|
<Flyout Placement="Bottom">
|
|
<StackPanel MinWidth="190">
|
|
<Button Classes="dropdownItem" Content="Undo" />
|
|
<Button Classes="dropdownItem" Content="Redo" />
|
|
<Border Classes="dropdownSeparator" />
|
|
<Button Classes="dropdownItem" Content="Preferences" />
|
|
</StackPanel>
|
|
</Flyout>
|
|
</Button.Flyout>
|
|
</Button>
|
|
|
|
<Button Classes="menuBarItem" Content="View">
|
|
<Button.Flyout>
|
|
<Flyout Placement="Bottom">
|
|
<StackPanel MinWidth="190">
|
|
<Button Classes="dropdownItem" Content="Toggle Sidebar" />
|
|
<Button Classes="dropdownItem" Content="Toggle Detail Panel" />
|
|
</StackPanel>
|
|
</Flyout>
|
|
</Button.Flyout>
|
|
</Button>
|
|
|
|
<Button Classes="menuBarItem" Content="Tools">
|
|
<Button.Flyout>
|
|
<Flyout Placement="Bottom">
|
|
<StackPanel MinWidth="190">
|
|
<Button Classes="dropdownItem" Content="SDK Manager" />
|
|
<Button Classes="dropdownItem" Content="Package Manager" />
|
|
</StackPanel>
|
|
</Flyout>
|
|
</Button.Flyout>
|
|
</Button>
|
|
|
|
<Button Classes="menuBarItem" Content="Help">
|
|
<Button.Flyout>
|
|
<Flyout Placement="Bottom">
|
|
<StackPanel MinWidth="190">
|
|
<Button Classes="dropdownItem" Content="Documentation" />
|
|
<Border Classes="dropdownSeparator" />
|
|
<Button Classes="dropdownItem" Content="About Nexvane Hub" />
|
|
</StackPanel>
|
|
</Flyout>
|
|
</Button.Flyout>
|
|
</Button>
|
|
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- ===== Body ===== -->
|
|
<Grid Grid.Row="1" ColumnDefinitions="210,*,360">
|
|
|
|
<!-- Sidebar navigation -->
|
|
<Border Grid.Column="0" Classes="sidebar">
|
|
<Grid RowDefinitions="*,Auto">
|
|
<StackPanel Grid.Row="0">
|
|
<Button Classes="navItem"
|
|
Classes.selected="{Binding CurrentSection, Converter={x:Static conv:EnumEqualsConverter.Instance}, ConverterParameter=Projects}"
|
|
Command="{Binding NavigateToCommand}"
|
|
CommandParameter="{x:Static vm:HubSection.Projects}"
|
|
Content="Projects" />
|
|
<Button Classes="navItem"
|
|
Classes.selected="{Binding CurrentSection, Converter={x:Static conv:EnumEqualsConverter.Instance}, ConverterParameter=Sdk}"
|
|
Command="{Binding NavigateToCommand}"
|
|
CommandParameter="{x:Static vm:HubSection.Sdk}"
|
|
Content="SDK" />
|
|
<Button Classes="navItem"
|
|
Classes.selected="{Binding CurrentSection, Converter={x:Static conv:EnumEqualsConverter.Instance}, ConverterParameter=Packages}"
|
|
Command="{Binding NavigateToCommand}"
|
|
CommandParameter="{x:Static vm:HubSection.Packages}"
|
|
Content="Packages" />
|
|
</StackPanel>
|
|
|
|
<Button Grid.Row="1" Classes="accountItem" Content="Account" />
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- Middle column: project list (with New folded in as its footer) / other sections -->
|
|
<Grid Grid.Column="1">
|
|
|
|
<!-- Everything for the Projects section - list + New - lives inside
|
|
ONE rounded, clipped container, so New reads as part of the
|
|
card rather than a separate floating button below it. -->
|
|
<Border Classes="listContainer"
|
|
Margin="16"
|
|
IsVisible="{Binding CurrentSection, Converter={x:Static conv:EnumEqualsConverter.Instance}, ConverterParameter=Projects}">
|
|
<Grid RowDefinitions="*,Auto">
|
|
<ScrollViewer Grid.Row="0" Padding="0,0,14,0">
|
|
<ListBox Classes="projectList"
|
|
ItemsSource="{Binding Projects}"
|
|
SelectedItem="{Binding SelectedProject}">
|
|
<ListBox.ItemTemplate>
|
|
<DataTemplate x:DataType="vm:ProjectItemViewModel">
|
|
<Border Classes="listRow">
|
|
<Grid ColumnDefinitions="56,*" Margin="14,10">
|
|
<Border Grid.Column="0" Classes="thumb" />
|
|
<StackPanel Grid.Column="1" Margin="12,0,0,0" VerticalAlignment="Center">
|
|
<TextBlock Classes="cardTitle" Text="{Binding Name}" />
|
|
<TextBlock Classes="cardSubtitle" Text="{Binding LastModifiedDisplay}" />
|
|
</StackPanel>
|
|
</Grid>
|
|
</Border>
|
|
</DataTemplate>
|
|
</ListBox.ItemTemplate>
|
|
</ListBox>
|
|
</ScrollViewer>
|
|
|
|
<Border Grid.Row="1" BorderBrush="{StaticResource DividerBrush}" BorderThickness="0,1,0,0">
|
|
<Button Classes="newProject"
|
|
Content="+ New"
|
|
Command="{Binding CreateNewProjectCommand}"
|
|
CornerRadius="0"
|
|
BorderThickness="0"
|
|
Margin="0" />
|
|
</Border>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<Border Padding="20"
|
|
IsVisible="{Binding CurrentSection, Converter={x:Static conv:EnumEqualsConverter.Instance}, ConverterParameter=Sdk}">
|
|
<TextBlock Classes="fieldLabel" Text="SDK management goes here." />
|
|
</Border>
|
|
|
|
<Border Padding="20"
|
|
IsVisible="{Binding CurrentSection, Converter={x:Static conv:EnumEqualsConverter.Instance}, ConverterParameter=Packages}">
|
|
<TextBlock Classes="fieldLabel" Text="Installed packages go here." />
|
|
</Border>
|
|
</Grid>
|
|
|
|
<!-- Right column: selected project detail - only part of the Projects
|
|
tab, not shown while viewing SDK/Packages. -->
|
|
<Border Grid.Column="2" Classes="detailPanel"
|
|
IsVisible="{Binding CurrentSection, Converter={x:Static conv:EnumEqualsConverter.Instance}, ConverterParameter=Projects}">
|
|
<Grid IsVisible="{Binding SelectedProject, Converter={x:Static avc:ObjectConverters.IsNotNull}}"
|
|
RowDefinitions="Auto,*,Auto"
|
|
Margin="18">
|
|
|
|
<TextBox Grid.Row="0"
|
|
Classes="input titleInput"
|
|
Text="{Binding SelectedProject.Name, Mode=TwoWay}" />
|
|
|
|
<ScrollViewer Grid.Row="1" Margin="0,14,0,0" Padding="0,0,14,0">
|
|
<StackPanel>
|
|
<Border Classes="thumbLarge" />
|
|
|
|
<ToggleButton Classes="sectionHeader"
|
|
Content="▾ Project"
|
|
IsChecked="{Binding IsProjectSectionExpanded}"
|
|
Margin="0,16,0,0" />
|
|
<StackPanel IsVisible="{Binding IsProjectSectionExpanded}" Margin="0,10,0,0" Spacing="10">
|
|
<Grid ColumnDefinitions="100,*">
|
|
<TextBlock Classes="fieldLabel" Text="Directory" />
|
|
<Border Grid.Column="1" Classes="fieldBox">
|
|
<TextBlock Classes="fieldValueMuted"
|
|
Text="{Binding SelectedProject.Directory}"
|
|
TextTrimming="CharacterEllipsis" />
|
|
</Border>
|
|
</Grid>
|
|
<Grid ColumnDefinitions="100,*">
|
|
<TextBlock Classes="fieldLabel" Text="Thumbnail" />
|
|
<TextBox Grid.Column="1"
|
|
Classes="input"
|
|
Text="{Binding SelectedProject.ThumbnailPath, Mode=TwoWay}"
|
|
Watermark="No thumbnail set" />
|
|
</Grid>
|
|
<Grid ColumnDefinitions="100,*">
|
|
<TextBlock Classes="fieldLabel" Text="Version" />
|
|
<TextBox Grid.Column="1"
|
|
Classes="input"
|
|
Text="{Binding SelectedProject.ProjectVersion, Mode=TwoWay}" />
|
|
</Grid>
|
|
</StackPanel>
|
|
|
|
<ToggleButton Classes="sectionHeader"
|
|
Content="▾ SDK"
|
|
IsChecked="{Binding IsSdkSectionExpanded}"
|
|
Margin="0,14,0,0" />
|
|
<StackPanel IsVisible="{Binding IsSdkSectionExpanded}" Margin="0,10,0,0" Spacing="10">
|
|
<Grid ColumnDefinitions="100,*">
|
|
<TextBlock Classes="fieldLabel" Text="Version" />
|
|
<TextBox Grid.Column="1"
|
|
Classes="input"
|
|
Text="{Binding SelectedProject.SdkVersion, Mode=TwoWay}" />
|
|
</Grid>
|
|
<Grid ColumnDefinitions="100,*">
|
|
<TextBlock Classes="fieldLabel" Text="Def. Compiler" />
|
|
<TextBox Grid.Column="1"
|
|
Classes="input"
|
|
Text="{Binding SelectedProject.DefaultCompiler, Mode=TwoWay}" />
|
|
</Grid>
|
|
<Grid ColumnDefinitions="100,*">
|
|
<TextBlock Classes="fieldLabel" Text="Def. Arch" />
|
|
<TextBox Grid.Column="1"
|
|
Classes="input"
|
|
Text="{Binding SelectedProject.DefaultArchitecture, Mode=TwoWay}" />
|
|
</Grid>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
|
|
<!-- Open/Delete as one rounded, clipped block with a hairline
|
|
divider between them - a visible seam so the pair doesn't
|
|
read as one smeared-together shape, but still no gap/margin
|
|
between the two buttons themselves. -->
|
|
<Border Grid.Row="2"
|
|
Margin="0,16,0,0"
|
|
CornerRadius="8"
|
|
ClipToBounds="True"
|
|
BorderBrush="{StaticResource CardBorderBrush}"
|
|
BorderThickness="1">
|
|
<StackPanel Spacing="0">
|
|
<Button Classes="primary"
|
|
Content="Open"
|
|
Command="{Binding OpenProjectCommand}"
|
|
HorizontalAlignment="Stretch"
|
|
HorizontalContentAlignment="Center"
|
|
CornerRadius="0"
|
|
BorderThickness="0" />
|
|
<Border Height="1" Background="{StaticResource CardBorderBrush}" />
|
|
<Button Classes="danger"
|
|
Content="Delete"
|
|
Command="{Binding DeleteProjectCommand}"
|
|
HorizontalAlignment="Stretch"
|
|
HorizontalContentAlignment="Center"
|
|
CornerRadius="0"
|
|
BorderThickness="0" />
|
|
</StackPanel>
|
|
</Border>
|
|
</Grid>
|
|
</Border>
|
|
|
|
</Grid>
|
|
</Grid>
|
|
</Window>
|