Extracted the headerview out of the MainWindow.axaml
This commit is contained in:
parent
81f6660da5
commit
ac01b81b35
@ -1,6 +1,7 @@
|
|||||||
<Application xmlns="https://github.com/avaloniaui"
|
<Application xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:fluent="using:Avalonia.Themes.Fluent"
|
xmlns:fluent="using:Avalonia.Themes.Fluent"
|
||||||
|
xmlns:conv="clr-namespace:XSDVisualiser.Desktop.Converters"
|
||||||
x:Class="XSDVisualiser.Desktop.App"
|
x:Class="XSDVisualiser.Desktop.App"
|
||||||
RequestedThemeVariant="Light">
|
RequestedThemeVariant="Light">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
@ -13,6 +14,12 @@
|
|||||||
<SolidColorBrush x:Key="MutedTextBrush" Color="#64748B"/>
|
<SolidColorBrush x:Key="MutedTextBrush" Color="#64748B"/>
|
||||||
<SolidColorBrush x:Key="SeparatorBrush" Color="#E2E8F0"/>
|
<SolidColorBrush x:Key="SeparatorBrush" Color="#E2E8F0"/>
|
||||||
<SolidColorBrush x:Key="BadgeBackgroundBrush" Color="#F1F5F9"/>
|
<SolidColorBrush x:Key="BadgeBackgroundBrush" Color="#F1F5F9"/>
|
||||||
|
|
||||||
|
<!-- Global converters -->
|
||||||
|
<conv:CardinalityToLabelConverter x:Key="CardinalityToLabel"/>
|
||||||
|
<conv:OptionalToBorderBrushConverter x:Key="OptionalToBrush"/>
|
||||||
|
<conv:OptionalToThicknessConverter x:Key="OptionalToThickness"/>
|
||||||
|
<conv:CollectionHasItemsConverter x:Key="HasItems"/>
|
||||||
</Application.Resources>
|
</Application.Resources>
|
||||||
|
|
||||||
<Application.Styles>
|
<Application.Styles>
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:m="clr-namespace:XSDVisualiser.Models;assembly=XSDVisualiser.Core"
|
xmlns:m="clr-namespace:XSDVisualiser.Models;assembly=XSDVisualiser.Core"
|
||||||
xmlns:conv="clr-namespace:XSDVisualiser.Desktop.Converters"
|
xmlns:conv="clr-namespace:XSDVisualiser.Desktop.Converters"
|
||||||
|
xmlns:views="clr-namespace:XSDVisualiser.Desktop.Views"
|
||||||
x:Class="XSDVisualiser.Desktop.MainWindow"
|
x:Class="XSDVisualiser.Desktop.MainWindow"
|
||||||
x:CompileBindings="False"
|
x:CompileBindings="False"
|
||||||
Title="XSD Visualiser" Width="1200" Height="800">
|
Title="XSD Visualiser" Width="1200" Height="800">
|
||||||
@ -14,26 +15,7 @@
|
|||||||
|
|
||||||
<Grid RowDefinitions="Auto,*" Margin="12">
|
<Grid RowDefinitions="Auto,*" Margin="12">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<DockPanel LastChildFill="False">
|
<views:HeaderView x:Name="Header" />
|
||||||
<TextBlock Text="XSD Visualiser" FontSize="20" FontWeight="SemiBold" Margin="0,0,12,0" DockPanel.Dock="Left"/>
|
|
||||||
|
|
||||||
<!-- Searchable dropdown for root elements -->
|
|
||||||
<AutoCompleteBox Width="320" Margin="0,0,12,0" Watermark="Search and choose a root element"
|
|
||||||
ItemsSource="{Binding RootElements}"
|
|
||||||
FilterMode="Contains"
|
|
||||||
MinimumPrefixLength="0">
|
|
||||||
<AutoCompleteBox.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<TextBlock Text="{Binding .}"/>
|
|
||||||
</DataTemplate>
|
|
||||||
</AutoCompleteBox.ItemTemplate>
|
|
||||||
<AutoCompleteBox.SelectedItem>
|
|
||||||
<Binding Path="SelectedRootElement" Mode="TwoWay"/>
|
|
||||||
</AutoCompleteBox.SelectedItem>
|
|
||||||
</AutoCompleteBox>
|
|
||||||
|
|
||||||
<Button Content="Open XSD and parse" x:Name="OpenBtn" Width="220"/>
|
|
||||||
</DockPanel>
|
|
||||||
|
|
||||||
<!-- Body: left tree | splitter | right details -->
|
<!-- Body: left tree | splitter | right details -->
|
||||||
<Grid Grid.Row="1" ColumnDefinitions="2*,Auto,*" RowDefinitions="*">
|
<Grid Grid.Row="1" ColumnDefinitions="2*,Auto,*" RowDefinitions="*">
|
||||||
|
|||||||
@ -6,6 +6,7 @@ using Avalonia.Threading;
|
|||||||
using XSDVisualiser.Core;
|
using XSDVisualiser.Core;
|
||||||
using XSDVisualiser.Models;
|
using XSDVisualiser.Models;
|
||||||
using XSDVisualiser.Desktop.ViewModels;
|
using XSDVisualiser.Desktop.ViewModels;
|
||||||
|
using XSDVisualiser.Desktop.Views;
|
||||||
|
|
||||||
namespace XSDVisualiser.Desktop
|
namespace XSDVisualiser.Desktop
|
||||||
{
|
{
|
||||||
@ -16,7 +17,10 @@ namespace XSDVisualiser.Desktop
|
|||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_openBtn = this.FindControl<Button>("OpenBtn");
|
var header = this.FindControl<HeaderView>("Header");
|
||||||
|
var btn = header?.FindControl<Button>("OpenBtn");
|
||||||
|
if (btn == null) return;
|
||||||
|
_openBtn = btn;
|
||||||
_openBtn.Click += OpenBtn_Click;
|
_openBtn.Click += OpenBtn_Click;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +33,7 @@ namespace XSDVisualiser.Desktop
|
|||||||
};
|
};
|
||||||
ofd.Filters!.Add(new FileDialogFilter { Name = "XSD schema", Extensions = { "xsd" } });
|
ofd.Filters!.Add(new FileDialogFilter { Name = "XSD schema", Extensions = { "xsd" } });
|
||||||
var files = await ofd.ShowAsync(this);
|
var files = await ofd.ShowAsync(this);
|
||||||
if (files != null && files.Length > 0)
|
if (files is { Length: > 0 })
|
||||||
{
|
{
|
||||||
await ParseAndShowAsync(files[0]);
|
await ParseAndShowAsync(files[0]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,15 +7,11 @@ using XSDVisualiser.Models;
|
|||||||
|
|
||||||
namespace XSDVisualiser.Desktop.ViewModels
|
namespace XSDVisualiser.Desktop.ViewModels
|
||||||
{
|
{
|
||||||
public class MainWindowViewModel : INotifyPropertyChanged
|
public class MainWindowViewModel(SchemaModel model) : INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
private SchemaModel _model;
|
private SchemaModel _model = model ?? throw new ArgumentNullException(nameof(model));
|
||||||
private SchemaNode? _selectedRootElement;
|
private SchemaNode? _selectedRootElement;
|
||||||
|
private SchemaNode? _selectedNode;
|
||||||
public MainWindowViewModel(SchemaModel model)
|
|
||||||
{
|
|
||||||
_model = model ?? throw new ArgumentNullException(nameof(model));
|
|
||||||
}
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler? PropertyChanged;
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
@ -29,15 +25,13 @@ namespace XSDVisualiser.Desktop.ViewModels
|
|||||||
get => _model;
|
get => _model;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!ReferenceEquals(_model, value))
|
if (ReferenceEquals(_model, value)) return;
|
||||||
{
|
|
||||||
_model = value ?? throw new ArgumentNullException(nameof(value));
|
_model = value ?? throw new ArgumentNullException(nameof(value));
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
OnPropertyChanged(nameof(RootElements));
|
OnPropertyChanged(nameof(RootElements));
|
||||||
OnPropertyChanged(nameof(VisibleRootElements));
|
OnPropertyChanged(nameof(VisibleRootElements));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<SchemaNode> RootElements => _model?.RootElements ?? Enumerable.Empty<SchemaNode>();
|
public IEnumerable<SchemaNode> RootElements => _model?.RootElements ?? Enumerable.Empty<SchemaNode>();
|
||||||
|
|
||||||
@ -46,23 +40,24 @@ namespace XSDVisualiser.Desktop.ViewModels
|
|||||||
get => _selectedRootElement;
|
get => _selectedRootElement;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (!EqualityComparer<SchemaNode?>.Default.Equals(_selectedRootElement, value))
|
if (EqualityComparer<SchemaNode?>.Default.Equals(_selectedRootElement, value)) return;
|
||||||
{
|
|
||||||
_selectedRootElement = value;
|
_selectedRootElement = value;
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
OnPropertyChanged(nameof(VisibleRootElements));
|
OnPropertyChanged(nameof(VisibleRootElements));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SchemaNode? SelectedNode
|
||||||
|
{
|
||||||
|
get => _selectedNode;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (EqualityComparer<SchemaNode?>.Default.Equals(_selectedNode, value)) return;
|
||||||
|
_selectedNode = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<SchemaNode> VisibleRootElements
|
public IEnumerable<SchemaNode> VisibleRootElements => SelectedRootElement != null ? [SelectedRootElement] : RootElements;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (SelectedRootElement != null)
|
|
||||||
return new[] { SelectedRootElement };
|
|
||||||
return RootElements;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
XSDVisualiser.Desktop/Views/HeaderView.axaml
Normal file
24
XSDVisualiser.Desktop/Views/HeaderView.axaml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
x:Class="XSDVisualiser.Desktop.Views.HeaderView"
|
||||||
|
x:CompileBindings="False">
|
||||||
|
<DockPanel LastChildFill="False">
|
||||||
|
<TextBlock Text="XSD Visualiser" FontSize="20" FontWeight="SemiBold" Margin="0,0,12,0" DockPanel.Dock="Left"/>
|
||||||
|
|
||||||
|
<AutoCompleteBox Width="320" Margin="0,0,12,0" Watermark="Search and choose a root element"
|
||||||
|
ItemsSource="{Binding RootElements}"
|
||||||
|
FilterMode="Contains"
|
||||||
|
MinimumPrefixLength="0">
|
||||||
|
<AutoCompleteBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock Text="{Binding .}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</AutoCompleteBox.ItemTemplate>
|
||||||
|
<AutoCompleteBox.SelectedItem>
|
||||||
|
<Binding Path="SelectedRootElement" Mode="TwoWay"/>
|
||||||
|
</AutoCompleteBox.SelectedItem>
|
||||||
|
</AutoCompleteBox>
|
||||||
|
|
||||||
|
<Button Content="Open XSD and parse" x:Name="OpenBtn" Width="220"/>
|
||||||
|
</DockPanel>
|
||||||
|
</UserControl>
|
||||||
11
XSDVisualiser.Desktop/Views/HeaderView.axaml.cs
Normal file
11
XSDVisualiser.Desktop/Views/HeaderView.axaml.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace XSDVisualiser.Desktop.Views;
|
||||||
|
|
||||||
|
public partial class HeaderView : UserControl
|
||||||
|
{
|
||||||
|
public HeaderView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
60
XSDVisualiser.Desktop/Views/LeftTreeView.axaml
Normal file
60
XSDVisualiser.Desktop/Views/LeftTreeView.axaml
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:m="clr-namespace:XSDVisualiser.Models;assembly=XSDVisualiser.Core"
|
||||||
|
x:Class="XSDVisualiser.Desktop.Views.LeftTreeView"
|
||||||
|
x:CompileBindings="False">
|
||||||
|
<Border Background="{DynamicResource PanelBackgroundBrush}"
|
||||||
|
BorderBrush="{DynamicResource PanelBorderBrush}"
|
||||||
|
BorderThickness="1" CornerRadius="6" Margin="0,8,8,0">
|
||||||
|
<ScrollViewer>
|
||||||
|
<TreeView x:Name="SchemaTree" ItemsSource="{Binding VisibleRootElements}" SelectedItem="{Binding SelectedNode, Mode=TwoWay}">
|
||||||
|
<TreeView.DataTemplates>
|
||||||
|
<TreeDataTemplate DataType="{x:Type m:SchemaNode}" ItemsSource="{Binding Children}">
|
||||||
|
<StackPanel>
|
||||||
|
<!-- Connector line from parent to this node (hidden for roots where ContentModel is null) -->
|
||||||
|
<Grid Margin="0,8,8,2" IsVisible="{Binding ContentModel, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||||
|
ColumnDefinitions="16,*">
|
||||||
|
<!-- leading small elbow -->
|
||||||
|
<Rectangle Grid.Column="0" Width="16" Height="2" Fill="{DynamicResource SeparatorBrush}" VerticalAlignment="Center"/>
|
||||||
|
<Grid Grid.Column="1">
|
||||||
|
<Rectangle Height="2" Fill="{DynamicResource SeparatorBrush}" VerticalAlignment="Center"/>
|
||||||
|
<TextBlock Text="{Binding Cardinality, Converter={StaticResource CardinalityToLabel}}"
|
||||||
|
Background="{DynamicResource BadgeBackgroundBrush}" Padding="6,0"
|
||||||
|
Foreground="{DynamicResource SubtleTextBrush}"
|
||||||
|
HorizontalAlignment="Center"/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Node content -->
|
||||||
|
<Border CornerRadius="4"
|
||||||
|
BorderBrush="{Binding Cardinality, Converter={StaticResource OptionalToBrush}}"
|
||||||
|
BorderThickness="{Binding Cardinality, Converter={StaticResource OptionalToThickness}}"
|
||||||
|
Padding="8" Margin="0,0,8,6" Background="{DynamicResource PanelBackgroundBrush}">
|
||||||
|
<StackPanel Orientation="Vertical" Spacing="2">
|
||||||
|
<!-- Name on its own line, prominent -->
|
||||||
|
<TextBlock Text="{Binding Name}" FontWeight="SemiBold"/>
|
||||||
|
|
||||||
|
<!-- Path/Namespace on its own line -->
|
||||||
|
<TextBlock Text="{Binding Namespace, StringFormat=Namespace: {0}}"
|
||||||
|
Foreground="{DynamicResource SubtleTextBrush}"/>
|
||||||
|
|
||||||
|
<!-- Type info on its own line (TypeName with fallback to BuiltInType) -->
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||||
|
<TextBlock Text="Type:" FontWeight="Medium"/>
|
||||||
|
<TextBlock Text="{Binding TypeName}"/>
|
||||||
|
<TextBlock Text="{Binding BuiltInType, StringFormat=({0})}"
|
||||||
|
Foreground="{DynamicResource MutedTextBrush}"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Optional: show content model as a subtle hint -->
|
||||||
|
<TextBlock Text="{Binding ContentModel, StringFormat=Model: {0}}"
|
||||||
|
Foreground="{DynamicResource SubtleTextBrush}" FontWeight="SemiBold"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</StackPanel>
|
||||||
|
</TreeDataTemplate>
|
||||||
|
</TreeView.DataTemplates>
|
||||||
|
</TreeView>
|
||||||
|
</ScrollViewer>
|
||||||
|
</Border>
|
||||||
|
</UserControl>
|
||||||
12
XSDVisualiser.Desktop/Views/LeftTreeView.axaml.cs
Normal file
12
XSDVisualiser.Desktop/Views/LeftTreeView.axaml.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace XSDVisualiser.Desktop.Views
|
||||||
|
{
|
||||||
|
public partial class LeftTreeView : UserControl
|
||||||
|
{
|
||||||
|
public LeftTreeView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user