Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev schema editing #284

Draft
wants to merge 2 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
using System.Windows.Input;
using Autodesk.Revit.DB.ExtensibleStorage;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RevitLookup.Services;
using RevitLookup.ViewModels.Contracts;
using RevitLookup.Views.Dialogs;
using RevitLookup.Views.Extensions;

namespace RevitLookup.Core.ComponentModel.Descriptors;
Expand Down Expand Up @@ -362,5 +364,24 @@ await RevitShell.AsyncEventHandler.RaiseAsync(_ =>
}
})
.SetShortcut(Key.Delete);

contextMenu.AddMenuItem("EditMenuItem")
.SetHeader("Edit values")
.SetAvailability(_element.IsValidObject)
.SetCommand(_element, async _ =>
{
var context = (ISnoopViewModel) contextMenu.DataContext;
try
{
var dialog = new SelectEntityDialog(context.ServiceProvider, _element);
await dialog.ShowAsync();
}
catch (Exception exception)
{
var logger = context.ServiceProvider.GetRequiredService<ILogger<ParameterDescriptor>>();
logger.LogError(exception, "Initialize EditParameterDialog error");
}
})
.SetShortcut(Key.F2);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright 2003-2024 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.

using System.Collections.ObjectModel;
using System.Reflection;
using Autodesk.Revit.DB.ExtensibleStorage;
using RevitLookup.Core;

namespace RevitLookup.ViewModels.Dialogs.ExtensibleStorage;

public sealed partial class EditEntityViewModel : ObservableObject
{
private readonly Entity _entity;
private readonly Element _element;
[ObservableProperty] private ObservableCollection<SimpleFieldDto> _descriptors = [];

public EditEntityViewModel(Entity entity, Element element)
{
_entity = entity;
_element = element;
var fields = entity.Schema.ListFields();
foreach (var field in fields)
{
if (field.ContainerType == ContainerType.Simple)

Check notice on line 41 in source/RevitLookup/ViewModels/Dialogs/ExtensibleStorage/EditEntityViewModel.cs

View workflow job for this annotation

GitHub Actions / Qodana for .NET

Invert 'if' statement to reduce nesting

Invert 'if' statement to reduce nesting
{
var method = entity.GetType().GetMethod(nameof(Entity.Get), [typeof(Field)])!;
var genericMethod = MakeGenericInvoker(field, method);
var value = genericMethod.Invoke(entity, [field]);

Descriptors.Add(new SimpleFieldDto
{
FieldType = field.ValueType,
Name = field.FieldName,
Value = value,
Unit = field.GetSpecTypeId()
});
}
}
}

private static MethodInfo MakeGenericInvoker(Field field, MethodInfo invoker)
{
var containerType = field.ContainerType switch
{
ContainerType.Simple => field.ValueType,
ContainerType.Array => typeof(IList<>).MakeGenericType(field.ValueType),
ContainerType.Map => typeof(IDictionary<,>).MakeGenericType(field.KeyType, field.ValueType),
_ => throw new ArgumentOutOfRangeException()
};

return invoker.MakeGenericMethod(containerType);
}

public async Task SaveValueAsync()
{
await RevitShell.AsyncEventHandler.RaiseAsync(_ =>
{
var transaction = new Transaction(_element.Document);
transaction.Start("Edit entity values");

foreach (var descriptor in Descriptors)
{
var type = descriptor.FieldType;
if (type == typeof(string))
{
_entity.Set(descriptor.Name, descriptor.Value.ToString());
}
else if (type == typeof(double))
{
if (double.TryParse(descriptor.Value.ToString(), out var value))
{
_entity.Set(descriptor.Name, value);
}
}
else if (type == typeof(int))
{
if (int.TryParse(descriptor.Value.ToString(), out var value))
{
_entity.Set(descriptor.Name, value);
}
}
else if (type == typeof(short))
{
if (short.TryParse(descriptor.Value.ToString(), out var value))
{
_entity.Set(descriptor.Name, value);
}
}
_element.SetEntity(_entity);
}

transaction.Commit();
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2003-2024 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.

namespace RevitLookup.ViewModels.Dialogs.ExtensibleStorage;

public class EntityDto
{
public required string EntityName { get; set; }
public required Guid Guid { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2003-2024 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.

using Autodesk.Revit.DB.ExtensibleStorage;
using RevitLookup.Views.Dialogs;

namespace RevitLookup.ViewModels.Dialogs.ExtensibleStorage;

public partial class SelectEntityViewModel : ObservableObject
{
private readonly Element _element;
[ObservableProperty] private EntityDto _selectedEntity;
public List<EntityDto> ExistedEntities { get; } = [];
public SelectEntityViewModel(Element element)
{
_element = element;
var schemas = Schema.ListSchemas();
foreach (var schema in schemas)
{
if (!schema.ReadAccessGranted()) return;
var entity = element.GetEntity(schema);
if (entity is not null && entity.Schema is not null)

Check notice on line 39 in source/RevitLookup/ViewModels/Dialogs/ExtensibleStorage/SelectEntityViewModel.cs

View workflow job for this annotation

GitHub Actions / Qodana for .NET

Merge sequential checks into single conditional access check

Merge sequential checks
{
ExistedEntities.Add(new EntityDto
{
EntityName = schema.SchemaName,
Guid = entity.SchemaGUID
});
}
}
}

public async Task ShowEditEntityDialogAsync(IServiceProvider serviceProvider)
{
var schema = Schema.Lookup(SelectedEntity.Guid);
var entity = _element.GetEntity(schema);
var dialog = new EditEntityValuesDialog(serviceProvider, _element, entity);
await dialog.ShowAsync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2003-2024 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.

namespace RevitLookup.ViewModels.Dialogs.ExtensibleStorage;

public partial class SimpleFieldDto : ObservableObject
{
[ObservableProperty] private object _value;
public string Name { get; set; }
public Type FieldType { get; set; }
public ForgeTypeId Unit { get; set; }
}
36 changes: 36 additions & 0 deletions source/RevitLookup/Views/Dialogs/EditEntityValuesDialog.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<Grid
x:Class="RevitLookup.Views.Dialogs.EditEntityValuesDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:dialogs="clr-namespace:RevitLookup.ViewModels.Dialogs.ExtensibleStorage"
xmlns:rl="http://revitlookup.com/xaml"
mc:Ignorable="d"
MinWidth="416"
d:DataContext="{d:DesignInstance dialogs:EditEntityViewModel}">
<DataGrid
IsReadOnly="False"
CanUserAddRows="False"
HeadersVisibility="Column"
CanUserReorderColumns="False"
AutoGenerateColumns="False"
ItemsSource="{Binding Descriptors}">
<DataGrid.Columns>
<DataGridTextColumn Header="Field name" Binding="{Binding Name}" />
<DataGridTemplateColumn Width="*" Header="Value">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<rl:TextBlock Text="{Binding Value}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<rl:TextBox
Text="{Binding Value}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
73 changes: 73 additions & 0 deletions source/RevitLookup/Views/Dialogs/EditEntityValuesDialog.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2003-2024 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.

using System.Windows;
using System.Windows.Controls;
using Autodesk.Revit.DB.ExtensibleStorage;
using Microsoft.Extensions.DependencyInjection;
using RevitLookup.Services;
using RevitLookup.ViewModels.Dialogs.ExtensibleStorage;
using Wpf.Ui;
using Wpf.Ui.Controls;

namespace RevitLookup.Views.Dialogs;

public sealed partial class EditEntityValuesDialog
{
private readonly IServiceProvider _serviceProvider;
private readonly EditEntityViewModel _viewModel;

public EditEntityValuesDialog(IServiceProvider serviceProvider, Element element, Entity entity)
{
_serviceProvider = serviceProvider;
_viewModel = new EditEntityViewModel(entity, element);

DataContext = _viewModel;
InitializeComponent();
}

public async Task ShowAsync()
{
var dialogOptions = new SimpleContentDialogCreateOptions
{
Title = "Edit entity field values",
Content = this,
PrimaryButtonText = "Save",
CloseButtonText = "Close",
DialogVerticalAlignment = VerticalAlignment.Center,
DialogHorizontalAlignment = HorizontalAlignment.Center,
HorizontalScrollVisibility = ScrollBarVisibility.Disabled,
VerticalScrollVisibility = ScrollBarVisibility.Disabled
};

var dialogResult = await _serviceProvider.GetRequiredService<IContentDialogService>().ShowSimpleDialogAsync(dialogOptions);
if (dialogResult != ContentDialogResult.Primary) return;

try
{
await _viewModel.SaveValueAsync();
}
catch (Exception exception)
{
var notificationService = _serviceProvider.GetRequiredService<NotificationService>();
notificationService.ShowWarning("Invalid data", exception.Message);
}
}
}
Loading
Loading