diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index f7682a1b..bf728d87 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -14,7 +14,7 @@ permissions:
on:
push:
- branches: [ master, viewer-take-2 ]
+ branches: [ master ]
pull_request:
branches: [ master ]
@@ -113,8 +113,8 @@ jobs:
LATEST_NET_ONLY: true
run: |
envsubst < src/Parquet/Globals.cs > g.tmp && mv g.tmp src/Parquet/Globals.cs
- dotnet restore src/Parquet.Floor.Desktop/Parquet.Floor.Desktop.csproj
- dotnet publish src/Parquet.Floor.Desktop/Parquet.Floor.Desktop.csproj -c release -r ${{ matrix.rid }} -o floor-pub/${{ matrix.rid }} /p:Version=${{ env.VERSION }} /p:FileVersion=${{ env.VERSION }} /p:AssemblyVersion=${{ env.ASM_VERSION }}
+ dotnet restore src/Parquet.Floor/Parquet.Floor.csproj
+ dotnet publish src/Parquet.Floor/Parquet.Floor.csproj -c release -r ${{ matrix.rid }} -o floor-pub/${{ matrix.rid }} /p:Version=${{ env.VERSION }} /p:FileVersion=${{ env.VERSION }} /p:AssemblyVersion=${{ env.ASM_VERSION }}
mkdir -p floor-dist
zip -r -9 -j floor-dist/floor-${{ matrix.rid }}-${{ env.VERSION }}.zip floor-pub/${{ matrix.rid }}/* -x *.pdb *.xml
diff --git a/docs/release-history.md b/docs/release-history.md
index 12b2dcd2..ba0feeb2 100644
--- a/docs/release-history.md
+++ b/docs/release-history.md
@@ -8,6 +8,10 @@
- `NetBox` was exposing some internal types (#451)
+### Experimental
+
+**Parquet Floor** (reference implementation of desktop viewer) user interface improvements.
+
## 4.20.0
### New features
diff --git a/src/Parquet.Floor.Desktop/Parquet.Floor.Desktop.csproj b/src/Parquet.Floor.Desktop/Parquet.Floor.Desktop.csproj
deleted file mode 100644
index 75e00be2..00000000
--- a/src/Parquet.Floor.Desktop/Parquet.Floor.Desktop.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
- WinExe
- net8.0
- enable
- true
- app.manifest
- floor
- true
- true
- true
- ../Parquet.Floor/Assets/icon.ico
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Parquet.Floor.Desktop/Properties/launchSettings.json b/src/Parquet.Floor.Desktop/Properties/launchSettings.json
deleted file mode 100644
index c1ff14d5..00000000
--- a/src/Parquet.Floor.Desktop/Properties/launchSettings.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "profiles": {
- "WSL": {
- "commandName": "WSL2",
- "distributionName": ""
- },
- "all_var": {
- "commandName": "Project",
- "commandLineArgs": "C:\\dev\\parquet-dotnet\\src\\Parquet.Test\\data\\all_var1.parquet"
- },
- "customer": {
- "commandName": "Project",
- "commandLineArgs": "C:\\dev\\parquet-dotnet\\src\\Parquet.Test\\data\\customer.impala.parquet"
- }
- }
-}
\ No newline at end of file
diff --git a/src/Parquet.Floor.Desktop/icon.ico b/src/Parquet.Floor.Desktop/icon.ico
deleted file mode 100644
index f0485eb5..00000000
Binary files a/src/Parquet.Floor.Desktop/icon.ico and /dev/null differ
diff --git a/src/Parquet.Floor/App.axaml b/src/Parquet.Floor/App.axaml
index 96cb1f72..241de23f 100644
--- a/src/Parquet.Floor/App.axaml
+++ b/src/Parquet.Floor/App.axaml
@@ -1,8 +1,8 @@
-
+ xmlns:actipro="http://schemas.actiprosoftware.com/avaloniaui"
+ xmlns:generation="using:ActiproSoftware.UI.Avalonia.Themes.Generation">
@@ -10,5 +10,11 @@
+
+
+
+
+
+
diff --git a/src/Parquet.Floor/App.axaml.cs b/src/Parquet.Floor/App.axaml.cs
index e9c5aea1..64e8ef46 100644
--- a/src/Parquet.Floor/App.axaml.cs
+++ b/src/Parquet.Floor/App.axaml.cs
@@ -18,14 +18,12 @@ public override void OnFrameworkInitializationCompleted() {
// Without this line you will get duplicate validations from both Avalonia and CT
BindingPlugins.DataValidators.RemoveAt(0);
+ var model = new MainViewModel();
+
if(ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) {
- desktop.MainWindow = new MainWindow {
- DataContext = new MainViewModel()
- };
+ desktop.MainWindow = new MainWindow() { DataContext = model };
} else if(ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform) {
- singleViewPlatform.MainView = new MainView {
- DataContext = new MainViewModel()
- };
+ singleViewPlatform.MainView = new MainView() { DataContext = model };
}
base.OnFrameworkInitializationCompleted();
diff --git a/src/Parquet.Floor/Assets/icons/col/bytearray.png b/src/Parquet.Floor/Assets/icons/col/bytearray.png
new file mode 100644
index 00000000..009bedaf
Binary files /dev/null and b/src/Parquet.Floor/Assets/icons/col/bytearray.png differ
diff --git a/src/Parquet.Floor/Assets/icons/col/list.png b/src/Parquet.Floor/Assets/icons/col/list.png
new file mode 100644
index 00000000..7dc9051a
Binary files /dev/null and b/src/Parquet.Floor/Assets/icons/col/list.png differ
diff --git a/src/Parquet.Floor/Assets/icons/col/map.png b/src/Parquet.Floor/Assets/icons/col/map.png
new file mode 100644
index 00000000..d83adafc
Binary files /dev/null and b/src/Parquet.Floor/Assets/icons/col/map.png differ
diff --git a/src/Parquet.Floor/Assets/icons/col/number.png b/src/Parquet.Floor/Assets/icons/col/number.png
new file mode 100644
index 00000000..3c90624a
Binary files /dev/null and b/src/Parquet.Floor/Assets/icons/col/number.png differ
diff --git a/src/Parquet.Floor/Assets/icons/col/string.png b/src/Parquet.Floor/Assets/icons/col/string.png
new file mode 100644
index 00000000..d6116eea
Binary files /dev/null and b/src/Parquet.Floor/Assets/icons/col/string.png differ
diff --git a/src/Parquet.Floor/Assets/icons/col/struct.png b/src/Parquet.Floor/Assets/icons/col/struct.png
new file mode 100644
index 00000000..81dda823
Binary files /dev/null and b/src/Parquet.Floor/Assets/icons/col/struct.png differ
diff --git a/src/Parquet.Floor/Assets/icons/diagram.png b/src/Parquet.Floor/Assets/icons/diagram.png
deleted file mode 100644
index 4ba7283a..00000000
Binary files a/src/Parquet.Floor/Assets/icons/diagram.png and /dev/null differ
diff --git a/src/Parquet.Floor/Assets/icons/glasses.png b/src/Parquet.Floor/Assets/icons/glasses.png
deleted file mode 100644
index 307c3ef8..00000000
Binary files a/src/Parquet.Floor/Assets/icons/glasses.png and /dev/null differ
diff --git a/src/Parquet.Floor/Assets/icons/information.png b/src/Parquet.Floor/Assets/icons/information.png
deleted file mode 100644
index 90580669..00000000
Binary files a/src/Parquet.Floor/Assets/icons/information.png and /dev/null differ
diff --git a/src/Parquet.Floor/Assets/icons/map.png b/src/Parquet.Floor/Assets/icons/map.png
deleted file mode 100644
index f406662d..00000000
Binary files a/src/Parquet.Floor/Assets/icons/map.png and /dev/null differ
diff --git a/src/Parquet.Floor/Assets/icons/open.png b/src/Parquet.Floor/Assets/icons/open.png
deleted file mode 100644
index fa351386..00000000
Binary files a/src/Parquet.Floor/Assets/icons/open.png and /dev/null differ
diff --git a/src/Parquet.Floor/Assets/icons/raw-extension.png b/src/Parquet.Floor/Assets/icons/raw-extension.png
deleted file mode 100644
index ed36e28c..00000000
Binary files a/src/Parquet.Floor/Assets/icons/raw-extension.png and /dev/null differ
diff --git a/src/Parquet.Floor/Assets/icons/trophy.png b/src/Parquet.Floor/Assets/icons/trophy.png
deleted file mode 100644
index 22d0d95d..00000000
Binary files a/src/Parquet.Floor/Assets/icons/trophy.png and /dev/null differ
diff --git a/src/Parquet.Floor/Extensions.cs b/src/Parquet.Floor/Extensions.cs
new file mode 100644
index 00000000..3c7fc426
--- /dev/null
+++ b/src/Parquet.Floor/Extensions.cs
@@ -0,0 +1,74 @@
+using System.Diagnostics;
+using Parquet.Meta;
+
+namespace Parquet.Floor {
+ static class Extensions {
+ public static string ToSimpleString(this LogicalType? lt) {
+ if(lt == null)
+ return string.Empty;
+
+ if(lt.UUID != null)
+ return "UUID";
+
+ if(lt.STRING != null)
+ return "STRING";
+
+ if(lt.MAP != null)
+ return "MAP";
+
+ if(lt.LIST != null)
+ return "LIST";
+
+ if(lt.ENUM != null)
+ return "ENUM";
+
+ if(lt.DECIMAL != null)
+ return $"DECIMAL (precision: {lt.DECIMAL.Precision}, scale: {lt.DECIMAL.Scale})";
+
+ if(lt.DATE != null)
+ return $"DATE";
+
+ if(lt.TIME != null) {
+ string unit = lt.TIME.Unit.MICROS != null
+ ? "MICROS"
+ : lt.TIME.Unit.MILLIS != null
+ ? "MILLIS"
+ : "NANOS";
+ return $"TIME (unit: {unit}, isAdjustedToUTC: {lt.TIME.IsAdjustedToUTC})";
+ }
+
+ if(lt.TIMESTAMP != null) {
+ string unit = lt.TIMESTAMP.Unit.MICROS != null
+ ? "MICROS"
+ : lt.TIMESTAMP.Unit.MILLIS != null
+ ? "MILLIS"
+ : "NANOS";
+ return $"TIMESTAMP (unit: {unit}, isAdjustedToUTC: {lt.TIMESTAMP.IsAdjustedToUTC})";
+ }
+
+ if(lt.INTEGER != null)
+ return $"INTEGER (bitWidth: {lt.INTEGER.BitWidth}, isSigned: {lt.INTEGER.IsSigned})";
+
+ if(lt.UNKNOWN != null)
+ return "UNKNOWN";
+
+ if(lt.JSON != null)
+ return "JSON";
+
+ if(lt.BSON != null)
+ return "BSON";
+
+ if(lt.UUID != null)
+ return "UUID";
+
+ return "?";
+ }
+
+ public static void OpenInBrowser(this string url) {
+ var p = new Process();
+ p.StartInfo.UseShellExecute = true;
+ p.StartInfo.FileName = url;
+ p.Start();
+ }
+ }
+}
diff --git a/src/Parquet.Floor/Parquet.Floor.csproj b/src/Parquet.Floor/Parquet.Floor.csproj
index 94591a56..ce1eef76 100644
--- a/src/Parquet.Floor/Parquet.Floor.csproj
+++ b/src/Parquet.Floor/Parquet.Floor.csproj
@@ -1,9 +1,17 @@
+ WinExe
net8.0
enable
latest
true
+ true
+ app.manifest
+ floor
+ true
+ true
+ true
+ Assets/icon.ico
@@ -15,12 +23,6 @@
-
-
-
-
-
-
@@ -29,15 +31,19 @@
+
+
+
+
+
+
-
-
-
-
+
+
@@ -50,4 +56,8 @@
DataView.axaml
+
+
+
+
diff --git a/src/Parquet.Floor.Desktop/Parquet.Floor.Desktop.csproj.user b/src/Parquet.Floor/Parquet.Floor.csproj.user
similarity index 86%
rename from src/Parquet.Floor.Desktop/Parquet.Floor.Desktop.csproj.user
rename to src/Parquet.Floor/Parquet.Floor.csproj.user
index 89082262..24c31915 100644
--- a/src/Parquet.Floor.Desktop/Parquet.Floor.Desktop.csproj.user
+++ b/src/Parquet.Floor/Parquet.Floor.csproj.user
@@ -4,6 +4,6 @@
ProjectDebugger
- all_var
+ clean
\ No newline at end of file
diff --git a/src/Parquet.Floor.Desktop/Program.cs b/src/Parquet.Floor/Program.cs
similarity index 80%
rename from src/Parquet.Floor.Desktop/Program.cs
rename to src/Parquet.Floor/Program.cs
index 5d0637a1..052cab80 100644
--- a/src/Parquet.Floor.Desktop/Program.cs
+++ b/src/Parquet.Floor/Program.cs
@@ -1,7 +1,9 @@
using System;
using Avalonia;
+using Projektanker.Icons.Avalonia.FontAwesome;
+using Projektanker.Icons.Avalonia;
-namespace Parquet.Floor.Desktop;
+namespace Parquet.Floor;
class Program {
// Initialization code. Don't use any Avalonia, third-party APIs or any
@@ -25,9 +27,12 @@ public static AppBuilder BuildAvaloniaApp() {
Console.WriteLine(ex);
}
+ IconProvider.Current
+ .Register();
+
return AppBuilder.Configure()
.UsePlatformDetect()
- .WithInterFont()
+ //.WithInterFont()
.LogToTrace();
}
diff --git a/src/Parquet.Floor/Styles.axaml b/src/Parquet.Floor/Styles.axaml
index 1436aa12..3713f2e2 100644
--- a/src/Parquet.Floor/Styles.axaml
+++ b/src/Parquet.Floor/Styles.axaml
@@ -1,17 +1,15 @@
+ xmlns:system="clr-namespace:System"
+ xmlns:i="https://github.com/projektanker/icons.avalonia">
-
-
+
+
+
@@ -39,6 +37,8 @@
+
+
@@ -62,18 +62,19 @@
+
-
+
+
+
-
@@ -84,7 +85,7 @@
@@ -92,18 +93,25 @@
-
+
-
+
+
@@ -111,7 +119,7 @@
-
-
-
-
@@ -172,7 +177,13 @@
+
+
diff --git a/src/Parquet.Floor/ViewModels/DataViewModel.cs b/src/Parquet.Floor/ViewModels/DataViewModel.cs
index 0ea365e1..9af1a565 100644
--- a/src/Parquet.Floor/ViewModels/DataViewModel.cs
+++ b/src/Parquet.Floor/ViewModels/DataViewModel.cs
@@ -10,6 +10,7 @@
using System.Collections.ObjectModel;
using System.Linq;
using Parquet.Meta;
+using Avalonia.Threading;
namespace Parquet.Floor.ViewModels;
@@ -30,18 +31,23 @@ public partial class DataViewModel : ViewModelBase {
public DataViewModel() {
#if DEBUG
if(Design.IsDesignMode) {
- Data = DesignData.Data;
File = new FileViewModel {
+ Schema = DesignData.Schema,
RowCount = 1012,
RowGroupCount = 3,
CreatedBy = "Parquet.Floor",
};
+ Data = DesignData.Data;
}
#endif
}
- public async Task InitReaderAsync(Stream fileStream) {
+ public async Task InitReaderAsync(FileViewModel? file, Stream fileStream) {
ParquetSerializer.UntypedResult fd = await ParquetSerializer.DeserializeAsync(fileStream);
- Data = fd.Data;
+
+ Dispatcher.UIThread.Invoke(() => {
+ File = file;
+ Data = fd.Data;
+ });
}
}
diff --git a/src/Parquet.Floor/ViewModels/FieldModel.cs b/src/Parquet.Floor/ViewModels/FieldModel.cs
index be0886e2..2addbb56 100644
--- a/src/Parquet.Floor/ViewModels/FieldModel.cs
+++ b/src/Parquet.Floor/ViewModels/FieldModel.cs
@@ -30,12 +30,14 @@ public FieldModel(Field field) {
public string? FieldId => Field.SchemaElement?.FieldId?.ToString();
- public string? LogicalType => FormatLogicalType();
+ public string? LogicalType => Field.SchemaElement?.LogicalType?.ToSimpleString();
public string DefinitionLevel => Field.MaxDefinitionLevel.ToString();
public string RepetitionLevel => Field.MaxRepetitionLevel.ToString();
+ public bool IsExpanded { get; set; } = true;
+
public List Children => Field switch {
StructField sf => sf.Fields.Select(f => new FieldModel(f)).ToList(),
MapField mf => new List {
@@ -62,63 +64,4 @@ public FieldModel(Field field) {
return "unknown";
}
}
-
- private string FormatLogicalType() {
-
- LogicalType? lt = Field.SchemaElement?.LogicalType;
-
- if(lt == null)
- return string.Empty;
-
- if(lt.UUID != null)
- return "UUID";
-
- if(lt.STRING != null)
- return "STRING";
-
- if(lt.MAP != null)
- return "MAP";
-
- if(lt.LIST != null)
- return "LIST";
-
- if(lt.ENUM != null)
- return "ENUM";
-
- if(lt.DECIMAL != null)
- return $"DECIMAL (precision: {lt.DECIMAL.Precision}, scale: {lt.DECIMAL.Scale})";
-
- if(lt.DATE != null)
- return $"DATE";
-
- if(lt.TIME != null) {
- string unit = lt.TIME.Unit.MICROS != null
- ? "MICROS"
- : lt.TIME.Unit.MILLIS != null
- ? "MILLIS"
- : "NANOS";
- return $"TIME (unit: {unit}, isAdjustedToUTC: {lt.TIME.IsAdjustedToUTC})";
- }
-
- if(lt.TIMESTAMP != null)
- return "TIMESTAMP";
-
- if(lt.INTEGER != null)
- return $"INTEGER (bitWidth: {lt.INTEGER.BitWidth}, isSigned: {lt.INTEGER.IsSigned})";
-
- if(lt.UNKNOWN != null)
- return "UNKNOWN";
-
- if(lt.JSON != null)
- return "JSON";
-
- if(lt.BSON != null)
- return "BSON";
-
- if(lt.UUID != null)
- return "UUID";
-
- return "?";
- }
-
}
diff --git a/src/Parquet.Floor/ViewModels/MainViewModel.cs b/src/Parquet.Floor/ViewModels/MainViewModel.cs
index 997236cd..49083a66 100644
--- a/src/Parquet.Floor/ViewModels/MainViewModel.cs
+++ b/src/Parquet.Floor/ViewModels/MainViewModel.cs
@@ -18,9 +18,18 @@ public partial class MainViewModel : ViewModelBase {
private Stream? _fileStream;
+ [ObservableProperty]
+ private string? _title;
+
+ [ObservableProperty]
+ private string? _subTitle;
+
[ObservableProperty]
private FileViewModel? _file;
+ [ObservableProperty]
+ private bool _hasFile;
+
[ObservableProperty]
private bool _hasError;
@@ -38,6 +47,10 @@ public partial class MainViewModel : ViewModelBase {
public DataViewModel Data { get; } = new DataViewModel();
public MainViewModel() {
+
+ Title = "Parquet Floor";
+ SubTitle = Parquet.Globals.Version;
+
string[] args = Environment.GetCommandLineArgs();
if(Design.IsDesignMode) {
@@ -49,6 +62,11 @@ public MainViewModel() {
}
}
+ public bool OpenHomePage() {
+ "https://github.com/aloneguid/parquet-dotnet".OpenInBrowser();
+ return true;
+ }
+
private void LoadDesignData() {
File = new FileViewModel {
Path = "design.parquet",
@@ -56,6 +74,7 @@ private void LoadDesignData() {
};
ErrorMessage = "This is a design-time error message.";
ErrorDetails = "This is a design-time error details message.\nLine 2";
+ HasFile = true;
}
public void LoadFromFile(string path) {
@@ -95,10 +114,9 @@ private async Task LoadAsync(Stream fileStream) {
CreatedBy = reader.Metadata?.CreatedBy
};
}
+ HasFile = true;
Schema.InitSchema(File.Schema);
- Data.File = File;
- await Data.InitReaderAsync(_fileStream);
-
+ await Data.InitReaderAsync(File, _fileStream);
} catch(Exception ex) {
HasError = true;
ErrorMessage = ex.Message;
diff --git a/src/Parquet.Floor/ViewModels/SchemaViewModel.cs b/src/Parquet.Floor/ViewModels/SchemaViewModel.cs
index b6d1b1b1..b9b3e077 100644
--- a/src/Parquet.Floor/ViewModels/SchemaViewModel.cs
+++ b/src/Parquet.Floor/ViewModels/SchemaViewModel.cs
@@ -41,7 +41,7 @@ public void InitSchema(ParquetSchema? schema) {
Columns = {
new HierarchicalExpanderColumn(
new TextColumn("Name", x => x.Name),
- x => x.Children),
+ x => x.Children, isExpandedSelector: x => x.IsExpanded),
//new TextColumn("Num children", x => x.NumChildren),
new TextColumn("Type", x => x.Type),
new TextColumn("Converted type", x => x.ConvertedType),
diff --git a/src/Parquet.Floor/Views/DataView.axaml b/src/Parquet.Floor/Views/DataView.axaml
index eaf99fe7..d2c42a97 100644
--- a/src/Parquet.Floor/Views/DataView.axaml
+++ b/src/Parquet.Floor/Views/DataView.axaml
@@ -4,38 +4,31 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:Parquet.Floor.ViewModels"
xmlns:pqs="clr-namespace:Parquet.Schema;assembly=Parquet"
- mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+ xmlns:i="https://github.com/projektanker/icons.avalonia"
+ mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="450"
x:Class="Parquet.Floor.Views.DataView"
x:DataType="vm:DataViewModel">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/src/Parquet.Floor/Views/DataView.axaml.cs b/src/Parquet.Floor/Views/DataView.axaml.cs
index 1d803b62..e75200a4 100644
--- a/src/Parquet.Floor/Views/DataView.axaml.cs
+++ b/src/Parquet.Floor/Views/DataView.axaml.cs
@@ -6,24 +6,22 @@
using Avalonia.Data;
using Avalonia.Threading;
using Parquet.Floor.ViewModels;
+using Parquet.Floor.Views.Templates;
using Parquet.Schema;
namespace Parquet.Floor.Views {
public partial class DataView : UserControl {
+
public DataView() {
InitializeComponent();
}
- public DataViewModel? ViewModel => DataContext as DataViewModel;
-
+ private DataViewModel? Model => DataContext as DataViewModel;
protected override void OnDataContextChanged(EventArgs e) {
-
- if(ViewModel != null) {
- ViewModel.PropertyChanged += ViewModel_PropertyChanged;
+ if(Model != null) {
+ Model.PropertyChanged += ViewModel_PropertyChanged;
}
-
- base.OnDataContextChanged(e);
}
private IEnumerable? BuildColumns(ParquetSchema schema) {
@@ -33,6 +31,7 @@ protected override void OnDataContextChanged(EventArgs e) {
? null
: schema.Fields.Select(f => new DataGridTemplateColumn {
Header = f.Name,
+ HeaderTemplate = new DataViewHeaderTemplate(f),
CellTemplate = new DataViewCellTemplate(f)
}).Cast().ToList();
}
@@ -40,23 +39,26 @@ protected override void OnDataContextChanged(EventArgs e) {
private void ViewModel_PropertyChanged(object? sender, PropertyChangedEventArgs e) {
Dispatcher.UIThread.Invoke(() => {
- if(ViewModel == null || ViewModel.File?.Schema == null)
+ if(Model?.File?.Schema == null)
return;
if(e.PropertyName == nameof(DataViewModel.File)) {
// copy the columns over, as DataGrid.Columns does not support binding
grid.Columns.Clear();
- IEnumerable? columns = BuildColumns(ViewModel.File.Schema);
+ IEnumerable? columns = BuildColumns(Model.File.Schema);
if(columns != null) {
foreach(DataGridColumn c in columns) {
grid.Columns.Add(c);
}
}
- }
+ }
});
}
+ private void DataGrid_CellPointerPressed(object? sender, Avalonia.Controls.DataGridCellPointerPressedEventArgs e) {
+ grid.SelectedItem = null;
+ }
}
}
diff --git a/src/Parquet.Floor/Views/MainView.axaml b/src/Parquet.Floor/Views/MainView.axaml
index ddfde7d4..60964d31 100644
--- a/src/Parquet.Floor/Views/MainView.axaml
+++ b/src/Parquet.Floor/Views/MainView.axaml
@@ -4,53 +4,101 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:Parquet.Floor.ViewModels"
xmlns:views="clr-namespace:Parquet.Floor.Views"
- mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="100"
+ xmlns:actipro="http://schemas.actiprosoftware.com/avaloniaui"
+ xmlns:i="https://github.com/projektanker/icons.avalonia"
+ xmlns:actiproImages="using:ActiproSoftware.UI.Avalonia.Images"
+ mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="200"
x:Class="Parquet.Floor.Views.MainView"
x:DataType="vm:MainViewModel">
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+ 0,0,20,0
+
+
+ 0,0,0,0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3,0,3,3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Parquet.Floor/Views/MainWindow.axaml b/src/Parquet.Floor/Views/MainWindow.axaml
index e06bd103..2b211dc0 100644
--- a/src/Parquet.Floor/Views/MainWindow.axaml
+++ b/src/Parquet.Floor/Views/MainWindow.axaml
@@ -8,5 +8,5 @@
x:Class="Parquet.Floor.Views.MainWindow"
Icon="/Assets/icon.ico"
Title="Floor">
-
+
diff --git a/src/Parquet.Floor/Views/MainWindow.axaml.cs b/src/Parquet.Floor/Views/MainWindow.axaml.cs
index 0b1ffed5..d73aa1ca 100644
--- a/src/Parquet.Floor/Views/MainWindow.axaml.cs
+++ b/src/Parquet.Floor/Views/MainWindow.axaml.cs
@@ -5,7 +5,5 @@ namespace Parquet.Floor.Views;
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
-
- Title = $"Parquet Floor v{Parquet.Globals.Version}";
}
}
\ No newline at end of file
diff --git a/src/Parquet.Floor/Views/DataViewCellTemplate.cs b/src/Parquet.Floor/Views/Templates/DataViewCellTemplate.cs
similarity index 80%
rename from src/Parquet.Floor/Views/DataViewCellTemplate.cs
rename to src/Parquet.Floor/Views/Templates/DataViewCellTemplate.cs
index 68bc684e..b7d57d14 100644
--- a/src/Parquet.Floor/Views/DataViewCellTemplate.cs
+++ b/src/Parquet.Floor/Views/Templates/DataViewCellTemplate.cs
@@ -7,12 +7,12 @@
using Avalonia.Layout;
using Parquet.Schema;
-namespace Parquet.Floor.Views {
+namespace Parquet.Floor.Views.Templates {
///
/// Implements pretty much all of the logic for rendering a parquet data cell, including complex types.
///
- internal class DataViewCellTemplate : IDataTemplate {
+ class DataViewCellTemplate : IDataTemplate {
private const string DataCellClassName = "data-cell";
private const string DataCellNullClassName = "data-cell-null";
@@ -47,16 +47,12 @@ private static TextBlock CreateTextBlock(string value, string? extraClassName =
Text = value
};
r.Classes.Add(DataCellClassName);
- if(extraClassName != null) {
- r.Classes.Add(extraClassName);
- }
+ if(extraClassName != null) r.Classes.Add(extraClassName);
return r;
}
public static Control BuildValue(object? value, Field f, int depth, string? extraClassName = null, bool forceData = false) {
- if(value == null) {
- return CreateNullTextBlock();
- }
+ if(value == null) return CreateNullTextBlock();
if(forceData || f.SchemaType == SchemaType.Data) {
TextBlock tb = CreateTextBlock(value.ToString()!, extraClassName);
@@ -68,8 +64,7 @@ public static Control BuildValue(object? value, Field f, int depth, string? extr
};
var structField = (StructField)f;
- if(value is IDictionary valueDictionary) {
- foreach(Field field in structField.Fields) {
+ if(value is IDictionary valueDictionary) foreach(Field field in structField.Fields) {
var vsp = new StackPanel {
Orientation = Orientation.Horizontal
@@ -82,7 +77,6 @@ public static Control BuildValue(object? value, Field f, int depth, string? extr
valueDictionary.TryGetValue(field.Name, out object? fieldValue);
vsp.Children.Add(BuildValue(fieldValue, field, depth + 1));
}
- }
return sp;
} else if(f.SchemaType == SchemaType.Map) {
@@ -92,8 +86,7 @@ public static Control BuildValue(object? value, Field f, int depth, string? extr
var mapField = (MapField)f;
- if(value is IDictionary valueDictionary) {
- foreach(DictionaryEntry entry in valueDictionary) {
+ if(value is IDictionary valueDictionary) foreach(DictionaryEntry entry in valueDictionary) {
var vsp = new StackPanel {
Orientation = Orientation.Horizontal
@@ -104,7 +97,6 @@ public static Control BuildValue(object? value, Field f, int depth, string? extr
//vsp.Children.Add(CreateTextBlock(": "));
vsp.Children.Add(BuildValue(entry.Value, mapField.Value, depth + 1));
}
- }
return sp;
} else if(f.SchemaType == SchemaType.List) {
@@ -112,11 +104,7 @@ public static Control BuildValue(object? value, Field f, int depth, string? extr
Orientation = Orientation.Vertical
};
var listField = (ListField)f;
- if(value is IEnumerable valueList) {
- foreach(object? entry in valueList) {
- sp.Children.Add(BuildValue(entry, listField.Item, depth + 1));
- }
- }
+ if(value is IEnumerable valueList) foreach(object? entry in valueList) sp.Children.Add(BuildValue(entry, listField.Item, depth + 1));
return sp;
}
@@ -127,13 +115,7 @@ public static Control Build(object? param, Field f, int depth) {
object? value = null;
- if(param is Dictionary row) {
- if(row.TryGetValue(f.Name, out object? mapValue)) {
- if(mapValue != null) {
- value = mapValue;
- }
- }
- }
+ if(param is Dictionary row) if(row.TryGetValue(f.Name, out object? mapValue)) if(mapValue != null) value = mapValue;
return BuildValue(value, f, depth);
}
diff --git a/src/Parquet.Floor/Views/Templates/DataViewHeaderTemplate.cs b/src/Parquet.Floor/Views/Templates/DataViewHeaderTemplate.cs
new file mode 100644
index 00000000..54490c24
--- /dev/null
+++ b/src/Parquet.Floor/Views/Templates/DataViewHeaderTemplate.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Parquet.Schema;
+using Avalonia.Controls;
+using Avalonia.Controls.Templates;
+using Avalonia.Layout;
+using Avalonia;
+using Parquet.Floor.ViewModels;
+using Avalonia.Platform;
+using Avalonia.Media.Imaging;
+
+namespace Parquet.Floor.Views.Templates {
+ class DataViewHeaderTemplate : IDataTemplate {
+ private readonly Field _field;
+
+ public DataViewHeaderTemplate(Field field) {
+ _field = field;
+ }
+
+ private static bool IsNumeric(Type t) =>
+ t == typeof(short) || t == typeof(int) || t == typeof(long) || t == typeof(decimal);
+
+ private static bool IsByteArray(Type t) =>
+ t == typeof(byte[]);
+
+ private static bool IsString(Type t) => t == typeof(string);
+
+ private Control CreateIcon() {
+
+ string? name = null;
+
+ switch(_field.SchemaType) {
+ case SchemaType.Data:
+ if(_field is DataField df) {
+ if(IsNumeric(df.ClrType)) {
+ name = "number";
+ } else if(IsString(df.ClrType)) {
+ name = "string";
+ } else if(IsByteArray(df.ClrType)) {
+ name = "bytearray";
+ }
+ }
+ break;
+ case SchemaType.Struct:
+ name = "struct";
+ break;
+ case SchemaType.Map:
+ name = "map";
+ break;
+ case SchemaType.List:
+ name = "list";
+ break;
+ }
+
+
+ if(name == null)
+ return new Control();
+
+ var image = new Image {
+ Source = new Bitmap(AssetLoader.Open(new Uri($"avares://floor/Assets/icons/col/{name}.png")))
+ };
+ image.Classes.Add("dt-icon");
+ return image;
+
+ }
+
+ public Control? Build(object? param) {
+
+ var r = new StackPanel {
+ Orientation = Orientation.Horizontal,
+ HorizontalAlignment = HorizontalAlignment.Stretch
+ };
+ r.Children.Add(new TextBlock {
+ Text = _field.Name
+ });
+ r.Children.Add(CreateIcon());
+
+ //r.SetValue(ToolTip.TipProperty, "...");
+ return r;
+ }
+ public bool Match(object? data) => true;
+ }
+}
diff --git a/src/Parquet.Floor.Desktop/app.manifest b/src/Parquet.Floor/app.manifest
similarity index 100%
rename from src/Parquet.Floor.Desktop/app.manifest
rename to src/Parquet.Floor/app.manifest
diff --git a/src/Parquet.sln b/src/Parquet.sln
index 11aa2164..7d2bd12f 100644
--- a/src/Parquet.sln
+++ b/src/Parquet.sln
@@ -37,12 +37,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Parquet.PerfRunner", "Parquet.PerfRunner\Parquet.PerfRunner.csproj", "{6325A9B7-32B4-464C-84F4-9B62BE630E90}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{712F0F85-C1D0-4176-BFCD-20F09CB59191}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Parquet.Floor", "Parquet.Floor\Parquet.Floor.csproj", "{882BE8ED-7F5F-4392-8884-CF602622E569}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Parquet.Floor.Desktop", "Parquet.Floor.Desktop\Parquet.Floor.Desktop.csproj", "{A6B74525-BDCB-4872-B530-3CBC50D11306}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -65,10 +61,6 @@ Global
{882BE8ED-7F5F-4392-8884-CF602622E569}.Debug|Any CPU.Build.0 = Debug|Any CPU
{882BE8ED-7F5F-4392-8884-CF602622E569}.Release|Any CPU.ActiveCfg = Release|Any CPU
{882BE8ED-7F5F-4392-8884-CF602622E569}.Release|Any CPU.Build.0 = Release|Any CPU
- {A6B74525-BDCB-4872-B530-3CBC50D11306}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A6B74525-BDCB-4872-B530-3CBC50D11306}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A6B74525-BDCB-4872-B530-3CBC50D11306}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A6B74525-BDCB-4872-B530-3CBC50D11306}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -78,8 +70,6 @@ Global
{AB829BBB-EF87-4038-8D32-E1C1629F357C} = {60294E19-6F8D-4D78-9A62-C50489095484}
{F28C5308-5410-4066-9DA8-4DDC8ACB0B5B} = {AB829BBB-EF87-4038-8D32-E1C1629F357C}
{6325A9B7-32B4-464C-84F4-9B62BE630E90} = {3F47B841-9074-4317-8ACA-0F2EEA34FA62}
- {882BE8ED-7F5F-4392-8884-CF602622E569} = {712F0F85-C1D0-4176-BFCD-20F09CB59191}
- {A6B74525-BDCB-4872-B530-3CBC50D11306} = {712F0F85-C1D0-4176-BFCD-20F09CB59191}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B5C12140-A3BF-47C9-A4AD-91F7C4682804}