From 80ddf15c23f64829ab170b62b37dda61e441500d Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 Jun 2023 13:21:50 +0300 Subject: [PATCH] Release 2024.0.6 (#169) * Cleanup * Update Nuke * Fix GetMaterialIds * DefinitionGroup support * Disable Show for ElementType * Demo project restore * Nuke update * Material area, volume support * Static members support * Update Changelog.md * Update nuget packages * Update Codeowners * FamilyInstance rooms support * Update Changelog.md * Separate UI thread * CleanUp * Remove debug RenderOptions * Fix initialisation render mode * Separate thread for UI (#166) * Separate UI thread * Remove debug RenderOptions * Fix initialisation render mode * Update Build.Installer * Fix context menu dispatcher * Icons support * Icons support (#167) * Pages virtualization * Category redirection support * Rework metadata builder * Fields, events support * Fix R24 compability * Bump version * Update Contributing.md * Update Changelog.md * Update Changelog.md * Update icon * Disable transition by default * Enhanced member support (#168) * Fields, events support * Fix R24 compability * Update icon * Disable transition by default * Icons update * Update Changelog.md --- Build/Build.Configuration.cs | 8 +- Build/Build.Installer.cs | 9 +- Changelog.md | 48 ++- Contributing.md | 9 +- RevitLookup/Application.cs | 35 +- RevitLookup/Commands/DashboardCommand.cs | 9 +- RevitLookup/Commands/EventMonitorCommand.cs | 9 +- RevitLookup/Commands/SearchElementsCommand.cs | 11 +- RevitLookup/Commands/SnoopDatabaseCommand.cs | 9 +- RevitLookup/Commands/SnoopDocumentCommand.cs | 9 +- RevitLookup/Commands/SnoopEdgeCommand.cs | 9 +- RevitLookup/Commands/SnoopFaceCommand.cs | 9 +- .../Commands/SnoopLinkedElementCommand.cs | 9 +- RevitLookup/Commands/SnoopPointCommand.cs | 9 +- RevitLookup/Commands/SnoopSelectionCommand.cs | 9 +- .../Commands/SnoopSubElementCommand.cs | 9 +- RevitLookup/Commands/SnoopViewCommand.cs | 9 +- .../Descriptors/CategoryDescriptor.cs | 3 +- .../Descriptors/CurveDescriptor.cs | 13 +- .../Descriptors/EdgeDescriptor.cs | 13 +- .../Descriptors/ElementDescriptor.cs | 15 +- .../Descriptors/ElementIdDescriptor.cs | 24 +- .../Descriptors/FaceDescriptor.cs | 13 +- .../Descriptors/HostObjectDescriptor.cs | 16 +- .../Descriptors/ParameterDescriptor.cs | 6 +- .../Descriptors/ScemaDescriptor.cs | 3 +- .../Descriptors/SolidDescriptor.cs | 23 +- .../Core/Contracts/IExtensionManager.cs | 3 +- RevitLookup/Core/Enums/MemberAttributes.cs | 9 +- .../Core/Extensions/DescriptorExtension.cs | 1 + .../Core/Extensions/ExtensionManager.cs | 63 +--- .../Core/Metadata/DescriptorBuilder.Build.cs | 93 ++++++ .../DescriptorBuilder.Enumeration.cs} | 20 +- .../Core/Metadata/DescriptorBuilder.Events.cs | 18 + .../Metadata/DescriptorBuilder.Extensions.cs | 41 +++ .../Core/Metadata/DescriptorBuilder.Fields.cs | 38 +++ .../Metadata/DescriptorBuilder.Methods.cs | 79 +++++ .../Metadata/DescriptorBuilder.Properties.cs | 79 +++++ .../Core/Metadata/DescriptorBuilder.cs | 171 ++++++++++ RevitLookup/Core/Objects/Descriptor.cs | 20 +- RevitLookup/Core/Objects/SnoopableObject.cs | 5 +- RevitLookup/Core/Utils/DescriptorBuilder.cs | 312 ------------------ RevitLookup/RibbonController.cs | 1 - .../Services/Contracts/ISettingsService.cs | 10 +- RevitLookup/Services/SettingsService.cs | 62 +++- .../Dialogs/SearchElementsViewModel.cs | 2 +- .../ViewModels/Pages/SettingsViewModel.cs | 57 +++- RevitLookup/ViewModels/Utils/SearchEngine.cs | 10 +- .../Views/Converters/DescriptorConverters.cs | 164 +++++++++ .../Converters/TreeViewSourceConverter.cs | 9 +- .../Views/Converters/ValueConverters.cs | 94 ------ RevitLookup/Views/Pages/DashboardView.xaml | 6 +- RevitLookup/Views/Pages/EventsView.xaml | 46 ++- RevitLookup/Views/Pages/EventsView.xaml.cs | 6 - RevitLookup/Views/Pages/SettingsView.xaml | 62 +++- RevitLookup/Views/Pages/SnoopView.xaml | 50 ++- RevitLookup/Views/Pages/SnoopView.xaml.cs | 9 +- RevitLookup/Views/Pages/SnoopViewBase.xaml.cs | 83 +++-- 58 files changed, 1230 insertions(+), 741 deletions(-) create mode 100644 RevitLookup/Core/Metadata/DescriptorBuilder.Build.cs rename RevitLookup/Core/{Enums/MemberType.cs => Metadata/DescriptorBuilder.Enumeration.cs} (70%) create mode 100644 RevitLookup/Core/Metadata/DescriptorBuilder.Events.cs create mode 100644 RevitLookup/Core/Metadata/DescriptorBuilder.Extensions.cs create mode 100644 RevitLookup/Core/Metadata/DescriptorBuilder.Fields.cs create mode 100644 RevitLookup/Core/Metadata/DescriptorBuilder.Methods.cs create mode 100644 RevitLookup/Core/Metadata/DescriptorBuilder.Properties.cs create mode 100644 RevitLookup/Core/Metadata/DescriptorBuilder.cs delete mode 100644 RevitLookup/Core/Utils/DescriptorBuilder.cs create mode 100644 RevitLookup/Views/Converters/DescriptorConverters.cs diff --git a/Build/Build.Configuration.cs b/Build/Build.Configuration.cs index 339cf16bf..500024fdd 100644 --- a/Build/Build.Configuration.cs +++ b/Build/Build.Configuration.cs @@ -20,10 +20,10 @@ protected override void OnBuildCreated() VersionMap = new() { - {"Release R21", "2021.2.5"}, - {"Release R22", "2022.2.5"}, - {"Release R23", "2023.2.5"}, - {"Release R24", "2024.0.5"} + {"Release R21", "2021.2.6"}, + {"Release R22", "2022.2.6"}, + {"Release R23", "2023.2.6"}, + {"Release R24", "2024.0.6"} }; } } \ No newline at end of file diff --git a/Build/Build.Installer.cs b/Build/Build.Installer.cs index 27b8f489b..38d141880 100644 --- a/Build/Build.Installer.cs +++ b/Build/Build.Installer.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using Nuke.Common; using Nuke.Common.Git; +using Nuke.Common.Utilities; using Serilog; using Serilog.Events; @@ -19,14 +20,14 @@ partial class Build var exePattern = $"*{installer.Name}.exe"; var exeFile = Directory.EnumerateFiles(installer.Directory, exePattern, SearchOption.AllDirectories).First(); - var publishDirectories = Directory.GetDirectories(project.Directory, "Publish*", SearchOption.AllDirectories); - if (publishDirectories.Length == 0) throw new Exception("No files were found to create an installer"); + var directories = Directory.GetDirectories(project.Directory, "Publish*", SearchOption.AllDirectories); + if (directories.Length == 0) throw new Exception("No files were found to create an installer"); - foreach (var publishDirectory in publishDirectories) + foreach (var directory in directories) { var proc = new Process(); proc.StartInfo.FileName = exeFile; - proc.StartInfo.Arguments = $@"""{publishDirectory}"""; + proc.StartInfo.Arguments = directory.DoubleQuoteIfNeeded(); proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.RedirectStandardError = true; proc.Start(); diff --git a/Changelog.md b/Changelog.md index 7abd0d717..c6ff81cd8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,52 @@ # Changelog -# next **2024.0.5** +# 2023-06-01 **2024.0.6** + +## Features + +### User interface + +* Icons + + Introducing a collection of new icons for properties, methods, fields, and events, ensuring a visually appealing representation + ![image](https://github.com/jeremytammik/RevitLookup/assets/20504884/ffbba475-e240-4928-bf02-68d8f75cbc4c) + +* Enhanced Performance with Separate UI Thread + + The RevitLookup user interface now operates in a dedicated thread, independent of Revit's workload. This architectural improvement significantly enhances smoothness and responsiveness + +* New Additional Setting Options + + Introducing a range of new setting options that expand customization capabilities and provide users with greater control over the tool's behavior + + +### Core + +* Class fields + + Introducing support for displaying class fields, enabling a comprehensive understanding of the class structure + ![image](https://github.com/jeremytammik/RevitLookup/assets/20504884/a4304fd4-4537-4bd2-8d90-88f46137a55a) + +* Class events + + Introducing support for displaying class events, facilitating better comprehension of event-driven programming within the class + ![image](https://github.com/jeremytammik/RevitLookup/assets/20504884/3b7ae347-e7bc-4642-89a0-99cd089f0abe) + +* Class private members + + Empowering developers with the ability to visualize and access class private fields, properties, methods, and events, providing a complete overview of the class implementation + ![image](https://github.com/jeremytammik/RevitLookup/assets/20504884/4c6e4459-cf2f-4d35-9b03-fe0b259b3c9a) + +## Improvements + +* ElementId Redirection to Category + + Implemented a helpful feature that automatically redirects ElementId to Category, whenever applicable. This simplifies navigation and enhances the user experience +* Content Virtualization + + Applied content virtualization to the dashboard and settings page, optimizing performance by efficiently managing large amounts of data and dynamically loading content as needed. This results in a smoother and more efficient user interaction + +# 2023-05-17 **2024.0.5** ## Features diff --git a/Contributing.md b/Contributing.md index d11b5d7df..d57256999 100644 --- a/Contributing.md +++ b/Contributing.md @@ -101,8 +101,9 @@ public sealed class ParameterDescriptor : Descriptor, IDescriptorExtension { public void RegisterExtensions(IExtensionManager manager) { - manager.Register(nameof(ParameterExtensions.AsBool), _parameter, extension => + manager.Register(_parameter, extension => { + extension.Name = nameof(ParameterExtensions.AsBool); extension.Result = extension.Value.AsBool(); }); } @@ -120,13 +121,9 @@ public sealed class ElementIdDescriptor : Descriptor, IDescriptorRedirection { public bool TryRedirect(Document context, string target, out object output) { - output = null; - if (target == nameof(Element.Id)) return false; - - var element = _elementId.ToElement(context); + output = _elementId.ToElement(context); if (element is null) return false; - output = element; return true; } } diff --git a/RevitLookup/Application.cs b/RevitLookup/Application.cs index fedad89b8..da38c6d57 100644 --- a/RevitLookup/Application.cs +++ b/RevitLookup/Application.cs @@ -22,7 +22,7 @@ using System.IO; using System.Windows.Interop; using System.Windows.Media; -using Autodesk.Revit.DB.Events; +using System.Windows.Threading; using Nice3point.Revit.Toolkit.External; using Nice3point.Revit.Toolkit.External.Handlers; using RevitLookup.Core; @@ -34,6 +34,7 @@ namespace RevitLookup; [UsedImplicitly] public class Application : ExternalApplication { + private static Thread _thread; public static ActionEventHandler ActionEventHandler { get; private set; } public static AsyncEventHandler> ExternalElementHandler { get; private set; } public static AsyncEventHandler> ExternalDescriptorHandler { get; private set; } @@ -47,6 +48,7 @@ public override async void OnStartup() var settingsService = Host.GetService(); RibbonController.CreatePanel(Application, settingsService); + RunDispatcher(); EnableHardwareRendering(settingsService); } @@ -76,17 +78,34 @@ private static void SaveSettings() settingsService.Save(); } - private void EnableHardwareRendering(ISettingsService settingsService) + private static void RunDispatcher() + { + _thread = new Thread(Dispatcher.Run); + _thread.SetApartmentState(ApartmentState.STA); + _thread.Start(); + + //Revit overrides render mode during initialization + //EventHandler is called after initialisation + ActionEventHandler.Raise(_ => RenderOptions.ProcessRenderMode = RenderMode.Default); + } + + public static void EnableHardwareRendering(ISettingsService settingsService) { if (!settingsService.IsHardwareRenderingAllowed) return; //Revit overrides render mode during initialization - Application.ControlledApplication.ApplicationInitialized += OnInitialized; + //EventHandler is called after initialisation + ActionEventHandler.Raise(_ => RenderOptions.ProcessRenderMode = RenderMode.Default); + } - void OnInitialized(object sender, ApplicationInitializedEventArgs args) - { - Application.ControlledApplication.ApplicationInitialized -= OnInitialized; - RenderOptions.ProcessRenderMode = RenderMode.Default; - } + public static void DisableHardwareRendering(ISettingsService settingsService) + { + if (settingsService.IsHardwareRenderingAllowed) return; + RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly; + } + + public static void Raise(Action action) + { + Dispatcher.FromThread(_thread)!.Invoke(action); } } \ No newline at end of file diff --git a/RevitLookup/Commands/DashboardCommand.cs b/RevitLookup/Commands/DashboardCommand.cs index 710e09946..13f06d72b 100644 --- a/RevitLookup/Commands/DashboardCommand.cs +++ b/RevitLookup/Commands/DashboardCommand.cs @@ -33,8 +33,11 @@ public class DashboardCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.ShowAttached(); - window.Scope.GetService().Navigate(typeof(DashboardView)); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.ShowAttached(); + window.Scope.GetService().Navigate(typeof(DashboardView)); + }); } } \ No newline at end of file diff --git a/RevitLookup/Commands/EventMonitorCommand.cs b/RevitLookup/Commands/EventMonitorCommand.cs index cec0e2f1b..baaf58646 100644 --- a/RevitLookup/Commands/EventMonitorCommand.cs +++ b/RevitLookup/Commands/EventMonitorCommand.cs @@ -33,8 +33,11 @@ public class EventMonitorCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.ShowAttached(); - window.Scope.GetService().Navigate(typeof(EventsView)); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.ShowAttached(); + window.Scope.GetService().Navigate(typeof(EventsView)); + }); } } \ No newline at end of file diff --git a/RevitLookup/Commands/SearchElementsCommand.cs b/RevitLookup/Commands/SearchElementsCommand.cs index 000e7146e..ed462d583 100644 --- a/RevitLookup/Commands/SearchElementsCommand.cs +++ b/RevitLookup/Commands/SearchElementsCommand.cs @@ -34,9 +34,12 @@ public class SearchElementsCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.ShowAttached(); - window.Scope.GetService().Navigate(typeof(DashboardView)); - window.Scope.GetService().OpenDialogCommand.Execute("search"); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.ShowAttached(); + window.Scope.GetService().Navigate(typeof(DashboardView)); + window.Scope.GetService().OpenDialogCommand.Execute("search"); + }); } } \ No newline at end of file diff --git a/RevitLookup/Commands/SnoopDatabaseCommand.cs b/RevitLookup/Commands/SnoopDatabaseCommand.cs index bff12777d..f5907e78d 100644 --- a/RevitLookup/Commands/SnoopDatabaseCommand.cs +++ b/RevitLookup/Commands/SnoopDatabaseCommand.cs @@ -32,8 +32,11 @@ public class SnoopDatabaseCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.Initialize(); - window.Scope.GetService()!.Snoop(SnoopableType.Database); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.Initialize(); + window.Scope.GetService()!.Snoop(SnoopableType.Database); + }); } } \ No newline at end of file diff --git a/RevitLookup/Commands/SnoopDocumentCommand.cs b/RevitLookup/Commands/SnoopDocumentCommand.cs index d81f16a9b..b6c2a164d 100644 --- a/RevitLookup/Commands/SnoopDocumentCommand.cs +++ b/RevitLookup/Commands/SnoopDocumentCommand.cs @@ -32,8 +32,11 @@ public class SnoopDocumentCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.Initialize(); - window.Scope.GetService()!.Snoop(SnoopableType.Document); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.Initialize(); + window.Scope.GetService()!.Snoop(SnoopableType.Document); + }); } } \ No newline at end of file diff --git a/RevitLookup/Commands/SnoopEdgeCommand.cs b/RevitLookup/Commands/SnoopEdgeCommand.cs index 3d57a1ada..969ffa721 100644 --- a/RevitLookup/Commands/SnoopEdgeCommand.cs +++ b/RevitLookup/Commands/SnoopEdgeCommand.cs @@ -32,8 +32,11 @@ public class SnoopEdgeCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.Initialize(); - window.Scope.GetService()!.Snoop(SnoopableType.Edge); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.Initialize(); + window.Scope.GetService()!.Snoop(SnoopableType.Edge); + }); } } \ No newline at end of file diff --git a/RevitLookup/Commands/SnoopFaceCommand.cs b/RevitLookup/Commands/SnoopFaceCommand.cs index 182e5fc4f..64bb8fe67 100644 --- a/RevitLookup/Commands/SnoopFaceCommand.cs +++ b/RevitLookup/Commands/SnoopFaceCommand.cs @@ -32,8 +32,11 @@ public class SnoopFaceCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.Initialize(); - window.Scope.GetService()!.Snoop(SnoopableType.Face); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.Initialize(); + window.Scope.GetService()!.Snoop(SnoopableType.Face); + }); } } \ No newline at end of file diff --git a/RevitLookup/Commands/SnoopLinkedElementCommand.cs b/RevitLookup/Commands/SnoopLinkedElementCommand.cs index f5f673bdb..b0a98f0cc 100644 --- a/RevitLookup/Commands/SnoopLinkedElementCommand.cs +++ b/RevitLookup/Commands/SnoopLinkedElementCommand.cs @@ -32,8 +32,11 @@ public class SnoopLinkedElementCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.Initialize(); - window.Scope.GetService()!.Snoop(SnoopableType.LinkedElement); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.Initialize(); + window.Scope.GetService()!.Snoop(SnoopableType.LinkedElement); + }); } } \ No newline at end of file diff --git a/RevitLookup/Commands/SnoopPointCommand.cs b/RevitLookup/Commands/SnoopPointCommand.cs index 8c2ec28a6..3b1c19abb 100644 --- a/RevitLookup/Commands/SnoopPointCommand.cs +++ b/RevitLookup/Commands/SnoopPointCommand.cs @@ -32,8 +32,11 @@ public class SnoopPointCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.Initialize(); - window.Scope.GetService()!.Snoop(SnoopableType.Point); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.Initialize(); + window.Scope.GetService()!.Snoop(SnoopableType.Point); + }); } } \ No newline at end of file diff --git a/RevitLookup/Commands/SnoopSelectionCommand.cs b/RevitLookup/Commands/SnoopSelectionCommand.cs index 2aaf1995a..b17689633 100644 --- a/RevitLookup/Commands/SnoopSelectionCommand.cs +++ b/RevitLookup/Commands/SnoopSelectionCommand.cs @@ -32,8 +32,11 @@ public class SnoopSelectionCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.Initialize(); - window.Scope.GetService()!.Snoop(SnoopableType.Selection); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.Initialize(); + window.Scope.GetService()!.Snoop(SnoopableType.Selection); + }); } } \ No newline at end of file diff --git a/RevitLookup/Commands/SnoopSubElementCommand.cs b/RevitLookup/Commands/SnoopSubElementCommand.cs index cc1e492bb..43154ea2f 100644 --- a/RevitLookup/Commands/SnoopSubElementCommand.cs +++ b/RevitLookup/Commands/SnoopSubElementCommand.cs @@ -32,8 +32,11 @@ public class SnoopSubElementCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.Initialize(); - window.Scope.GetService()!.Snoop(SnoopableType.SubElement); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.Initialize(); + window.Scope.GetService()!.Snoop(SnoopableType.SubElement); + }); } } \ No newline at end of file diff --git a/RevitLookup/Commands/SnoopViewCommand.cs b/RevitLookup/Commands/SnoopViewCommand.cs index aac18aea8..d9c1e4e2a 100644 --- a/RevitLookup/Commands/SnoopViewCommand.cs +++ b/RevitLookup/Commands/SnoopViewCommand.cs @@ -32,8 +32,11 @@ public class SnoopViewCommand : ExternalCommand { public override void Execute() { - var window = Host.GetService(); - window.Initialize(); - window.Scope.GetService()!.Snoop(SnoopableType.View); + RevitLookup.Application.Raise(() => + { + var window = Host.GetService(); + window.Initialize(); + window.Scope.GetService()!.Snoop(SnoopableType.View); + }); } } \ No newline at end of file diff --git a/RevitLookup/Core/ComponentModel/Descriptors/CategoryDescriptor.cs b/RevitLookup/Core/ComponentModel/Descriptors/CategoryDescriptor.cs index c80ae9e5d..3656d593b 100644 --- a/RevitLookup/Core/ComponentModel/Descriptors/CategoryDescriptor.cs +++ b/RevitLookup/Core/ComponentModel/Descriptors/CategoryDescriptor.cs @@ -37,8 +37,9 @@ public CategoryDescriptor(Category category) public void RegisterExtensions(IExtensionManager manager) { - manager.Register("GetElements", _category, extension => + manager.Register(_category, extension => { + extension.Name = "GetElements"; extension.Result = extension.Context #if R23_OR_GREATER .GetInstances(_category.BuiltInCategory); diff --git a/RevitLookup/Core/ComponentModel/Descriptors/CurveDescriptor.cs b/RevitLookup/Core/ComponentModel/Descriptors/CurveDescriptor.cs index 74b9dda84..f47d0904f 100644 --- a/RevitLookup/Core/ComponentModel/Descriptors/CurveDescriptor.cs +++ b/RevitLookup/Core/ComponentModel/Descriptors/CurveDescriptor.cs @@ -45,11 +45,14 @@ public MenuItem[] RegisterMenu() MenuItem.Create("Show curve") .AddCommand(_curve, curve => { - if (RevitApi.UiDocument is null) return; - if (curve.Reference is null) return; - var element = curve.Reference.ElementId.ToElement(RevitApi.Document); - if (element is not null) RevitApi.UiDocument.ShowElements(element); - RevitApi.UiDocument.Selection.SetReferences(new List(1) {curve.Reference}); + Application.ActionEventHandler.Raise(_ => + { + if (RevitApi.UiDocument is null) return; + if (curve.Reference is null) return; + var element = curve.Reference.ElementId.ToElement(RevitApi.Document); + if (element is not null) RevitApi.UiDocument.ShowElements(element); + RevitApi.UiDocument.Selection.SetReferences(new List(1) {curve.Reference}); + }); }) .AddGesture(ModifierKeys.Alt, Key.F7) }; diff --git a/RevitLookup/Core/ComponentModel/Descriptors/EdgeDescriptor.cs b/RevitLookup/Core/ComponentModel/Descriptors/EdgeDescriptor.cs index ba9bffeb4..1c5127339 100644 --- a/RevitLookup/Core/ComponentModel/Descriptors/EdgeDescriptor.cs +++ b/RevitLookup/Core/ComponentModel/Descriptors/EdgeDescriptor.cs @@ -45,11 +45,14 @@ public MenuItem[] RegisterMenu() MenuItem.Create("Show edge") .AddCommand(_edge, edge => { - if (RevitApi.UiDocument is null) return; - if (edge.Reference is null) return; - var element = edge.Reference.ElementId.ToElement(RevitApi.Document); - if (element is not null) RevitApi.UiDocument.ShowElements(element); - RevitApi.UiDocument.Selection.SetReferences(new List(1) {edge.Reference}); + Application.ActionEventHandler.Raise(_ => + { + if (RevitApi.UiDocument is null) return; + if (edge.Reference is null) return; + var element = edge.Reference.ElementId.ToElement(RevitApi.Document); + if (element is not null) RevitApi.UiDocument.ShowElements(element); + RevitApi.UiDocument.Selection.SetReferences(new List(1) {edge.Reference}); + }); }) .AddGesture(ModifierKeys.Alt, Key.F7) }; diff --git a/RevitLookup/Core/ComponentModel/Descriptors/ElementDescriptor.cs b/RevitLookup/Core/ComponentModel/Descriptors/ElementDescriptor.cs index 92f9314f0..11b4b24d4 100644 --- a/RevitLookup/Core/ComponentModel/Descriptors/ElementDescriptor.cs +++ b/RevitLookup/Core/ComponentModel/Descriptors/ElementDescriptor.cs @@ -46,9 +46,12 @@ public MenuItem[] RegisterMenu() MenuItem.Create("Show element") .AddCommand(_element, element => { - if (RevitApi.UiDocument is null) return; - RevitApi.UiDocument.ShowElements(element); - RevitApi.UiDocument.Selection.SetElementIds(new List(1) {element.Id}); + Application.ActionEventHandler.Raise(_ => + { + if (RevitApi.UiDocument is null) return; + RevitApi.UiDocument.ShowElements(element); + RevitApi.UiDocument.Selection.SetElementIds(new List(1) {element.Id}); + }); }) .AddGesture(ModifierKeys.Alt, Key.F7) }; @@ -56,12 +59,14 @@ public MenuItem[] RegisterMenu() public void RegisterExtensions(IExtensionManager manager) { - manager.Register(nameof(ElementExtensions.CanBeMirrored), _element, extension => + manager.Register(_element, extension => { + extension.Name = nameof(ElementExtensions.CanBeMirrored); extension.Result = extension.Value.CanBeMirrored(); }); - manager.Register(nameof(GeometryExtensions.GetJoinedElements), _element, extension => + manager.Register(_element, extension => { + extension.Name = nameof(GeometryExtensions.GetJoinedElements); extension.Result = extension.Value.GetJoinedElements(); }); } diff --git a/RevitLookup/Core/ComponentModel/Descriptors/ElementIdDescriptor.cs b/RevitLookup/Core/ComponentModel/Descriptors/ElementIdDescriptor.cs index 08471b137..f39a0a76f 100644 --- a/RevitLookup/Core/ComponentModel/Descriptors/ElementIdDescriptor.cs +++ b/RevitLookup/Core/ComponentModel/Descriptors/ElementIdDescriptor.cs @@ -38,11 +38,27 @@ public bool TryRedirect(Document context, string target, out object output) { output = null; if (target == nameof(Element.Id)) return false; + if (_elementId == ElementId.InvalidElementId) return false; - var element = _elementId.ToElement(context); - if (element is null) return false; +#if R24_OR_GREATER + if (_elementId.Value is > -3000000 and < -2000000) +#else + if (_elementId.IntegerValue is > -3000000 and < -2000000) +#endif + { + var element = Category.GetCategory(context, _elementId); + if (element is null) return false; - output = element; - return true; + output = element; + return true; + } + else + { + var element = _elementId.ToElement(context); + if (element is null) return false; + + output = element; + return true; + } } } \ No newline at end of file diff --git a/RevitLookup/Core/ComponentModel/Descriptors/FaceDescriptor.cs b/RevitLookup/Core/ComponentModel/Descriptors/FaceDescriptor.cs index e59b3cf55..493dbac1f 100644 --- a/RevitLookup/Core/ComponentModel/Descriptors/FaceDescriptor.cs +++ b/RevitLookup/Core/ComponentModel/Descriptors/FaceDescriptor.cs @@ -44,11 +44,14 @@ public MenuItem[] RegisterMenu() MenuItem.Create("Show face") .AddCommand(_face, face => { - if (RevitApi.UiDocument is null) return; - if (face.Reference is null) return; - var element = face.Reference.ElementId.ToElement(RevitApi.Document); - if (element is not null) RevitApi.UiDocument.ShowElements(element); - RevitApi.UiDocument.Selection.SetReferences(new List(1) {face.Reference}); + Application.ActionEventHandler.Raise(_ => + { + if (RevitApi.UiDocument is null) return; + if (face.Reference is null) return; + var element = face.Reference.ElementId.ToElement(RevitApi.Document); + if (element is not null) RevitApi.UiDocument.ShowElements(element); + RevitApi.UiDocument.Selection.SetReferences(new List(1) {face.Reference}); + }); }) .AddGesture(ModifierKeys.Alt, Key.F7) }; diff --git a/RevitLookup/Core/ComponentModel/Descriptors/HostObjectDescriptor.cs b/RevitLookup/Core/ComponentModel/Descriptors/HostObjectDescriptor.cs index 639635dcb..fe7b4491f 100644 --- a/RevitLookup/Core/ComponentModel/Descriptors/HostObjectDescriptor.cs +++ b/RevitLookup/Core/ComponentModel/Descriptors/HostObjectDescriptor.cs @@ -36,20 +36,22 @@ public HostObjectDescriptor(HostObject hostObject) : base(hostObject) public new void RegisterExtensions(IExtensionManager manager) { - manager.Register(nameof(HostExtensions.GetBottomFaces), _hostObject, extension => + manager.Register(_hostObject, extension => { + extension.Name = nameof(HostExtensions.GetBottomFaces); extension.Result = extension.Value.GetBottomFaces(); }); - manager.Register(nameof(HostExtensions.GetTopFaces), _hostObject, extension => + manager.Register(_hostObject, extension => { + extension.Name = nameof(HostExtensions.GetTopFaces); extension.Result = extension.Value.GetTopFaces(); }); - manager.Register(nameof(HostExtensions.GetSideFaces), _hostObject, extension => + manager.Register(_hostObject, extension => { - var extensionResult = new ResolveSet(2); - extensionResult.AppendVariant(extension.Value.GetSideFaces(ShellLayerType.Interior), "Interior"); - extensionResult.AppendVariant(extension.Value.GetSideFaces(ShellLayerType.Exterior), "Exterior"); - extension.Result = extensionResult; + extension.Name = nameof(HostExtensions.GetSideFaces); + extension.Result = new ResolveSet(2) + .AppendVariant(extension.Value.GetSideFaces(ShellLayerType.Interior), "Interior") + .AppendVariant(extension.Value.GetSideFaces(ShellLayerType.Exterior), "Exterior"); }); } diff --git a/RevitLookup/Core/ComponentModel/Descriptors/ParameterDescriptor.cs b/RevitLookup/Core/ComponentModel/Descriptors/ParameterDescriptor.cs index e18b6efff..2df3f536e 100644 --- a/RevitLookup/Core/ComponentModel/Descriptors/ParameterDescriptor.cs +++ b/RevitLookup/Core/ComponentModel/Descriptors/ParameterDescriptor.cs @@ -37,13 +37,15 @@ public ParameterDescriptor(Parameter parameter) public void RegisterExtensions(IExtensionManager manager) { - manager.Register(nameof(ParameterExtensions.AsBool), _parameter, extension => + manager.Register(_parameter, extension => { + extension.Name = nameof(ParameterExtensions.AsBool); extension.Result = extension.Value.AsBool(); }); - manager.Register(nameof(ParameterExtensions.AsColor), _parameter, extension => + manager.Register(_parameter, extension => { + extension.Name = nameof(ParameterExtensions.AsColor); extension.Result = extension.Value.AsColor(); }); } diff --git a/RevitLookup/Core/ComponentModel/Descriptors/ScemaDescriptor.cs b/RevitLookup/Core/ComponentModel/Descriptors/ScemaDescriptor.cs index 133d89944..2db153baa 100644 --- a/RevitLookup/Core/ComponentModel/Descriptors/ScemaDescriptor.cs +++ b/RevitLookup/Core/ComponentModel/Descriptors/ScemaDescriptor.cs @@ -36,8 +36,9 @@ public SchemaDescriptor(Schema schema) public void RegisterExtensions(IExtensionManager manager) { - manager.Register("GetElements", _schema, extension => + manager.Register(_schema, extension => { + extension.Name = "GetElements"; extension.Result = extension.Context .GetElements() .WherePasses(new ExtensibleStorageFilter(extension.Value.GUID)) diff --git a/RevitLookup/Core/ComponentModel/Descriptors/SolidDescriptor.cs b/RevitLookup/Core/ComponentModel/Descriptors/SolidDescriptor.cs index 8ef60b1b5..b81a5da95 100644 --- a/RevitLookup/Core/ComponentModel/Descriptors/SolidDescriptor.cs +++ b/RevitLookup/Core/ComponentModel/Descriptors/SolidDescriptor.cs @@ -44,18 +44,21 @@ public MenuItem[] RegisterMenu() MenuItem.Create("Show solid") .AddCommand(_solid, solid => { - if (RevitApi.UiDocument is null) return; - var references = solid.Faces - .Cast() - .Select(face => face.Reference) - .Where(reference => reference is not null) - .ToList(); + Application.ActionEventHandler.Raise(_ => + { + if (RevitApi.UiDocument is null) return; + var references = solid.Faces + .Cast() + .Select(face => face.Reference) + .Where(reference => reference is not null) + .ToList(); - if (references.Count == 0) return; + if (references.Count == 0) return; - var element = references[0].ElementId.ToElement(RevitApi.Document); - if (element is not null) RevitApi.UiDocument.ShowElements(element); - RevitApi.UiDocument.Selection.SetReferences(references); + var element = references[0].ElementId.ToElement(RevitApi.Document); + if (element is not null) RevitApi.UiDocument.ShowElements(element); + RevitApi.UiDocument.Selection.SetReferences(references); + }); }) .AddGesture(ModifierKeys.Alt, Key.F7) }; diff --git a/RevitLookup/Core/Contracts/IExtensionManager.cs b/RevitLookup/Core/Contracts/IExtensionManager.cs index e5ac01664..2d854fb24 100644 --- a/RevitLookup/Core/Contracts/IExtensionManager.cs +++ b/RevitLookup/Core/Contracts/IExtensionManager.cs @@ -24,6 +24,5 @@ namespace RevitLookup.Core.Contracts; public interface IExtensionManager { - void Register(string name, Func result); - void Register(string name, T value, Action> extension); + void Register(T value, Action> extension); } \ No newline at end of file diff --git a/RevitLookup/Core/Enums/MemberAttributes.cs b/RevitLookup/Core/Enums/MemberAttributes.cs index 722113deb..7de6b73f0 100644 --- a/RevitLookup/Core/Enums/MemberAttributes.cs +++ b/RevitLookup/Core/Enums/MemberAttributes.cs @@ -23,6 +23,11 @@ namespace RevitLookup.Core.Enums; [Flags] public enum MemberAttributes { - Private = 1, - Static = 2 + Private = 0b1, + Static = 0b10, + Field = 0b100, + Property = 0b1000, + Method = 0b10000, + Extension = 0b100000, + Event = 0b1000000 } \ No newline at end of file diff --git a/RevitLookup/Core/Extensions/DescriptorExtension.cs b/RevitLookup/Core/Extensions/DescriptorExtension.cs index c09fad78d..a764e258e 100644 --- a/RevitLookup/Core/Extensions/DescriptorExtension.cs +++ b/RevitLookup/Core/Extensions/DescriptorExtension.cs @@ -27,4 +27,5 @@ public sealed class DescriptorExtension public required Document Context { get; init; } public required T Value { get; init; } public object Result { get; set; } + public string Name { get; set; } } \ No newline at end of file diff --git a/RevitLookup/Core/Extensions/ExtensionManager.cs b/RevitLookup/Core/Extensions/ExtensionManager.cs index e35e9e84f..e9199c3d9 100644 --- a/RevitLookup/Core/Extensions/ExtensionManager.cs +++ b/RevitLookup/Core/Extensions/ExtensionManager.cs @@ -19,28 +19,22 @@ // (Rights in Technical Data and Computer Software), as applicable. using Autodesk.Revit.DB; -using RevitLookup.Core.ComponentModel.Descriptors; using RevitLookup.Core.Contracts; -using RevitLookup.Core.Enums; -using RevitLookup.Core.Objects; -using RevitLookup.Core.Utils; namespace RevitLookup.Core.Extensions; public sealed class ExtensionManager : IExtensionManager { private readonly Document _context; - private readonly Descriptor _descriptor; - public ExtensionManager(Document context, Descriptor descriptor) + public ExtensionManager(Document context) { _context = context; - _descriptor = descriptor; } - public List Descriptors { get; } = new(); + public Dictionary ValuesMap { get; } = new(); - public void Register(string name, T value, Action> extension) + public void Register(T value, Action> extension) { var descriptorExtension = new DescriptorExtension { @@ -48,61 +42,14 @@ public void Register(string name, T value, Action> ext Context = _context }; - var descriptor = new ObjectDescriptor - { - Name = name, - Type = _descriptor.Type, - MemberType = MemberType.Extension - }; - try { extension.Invoke(descriptorExtension); - descriptor.Value = EvaluateDescriptorValue(descriptorExtension.Result); - } - catch (Exception exception) - { - descriptor.Value = new SnoopableObject(_context, exception); - } - - Descriptors.Add(descriptor); - } - - public void Register(string name, Func result) - { - var descriptor = new ObjectDescriptor - { - Name = name, - Type = _descriptor.Type, - MemberType = MemberType.Extension - }; - - try - { - descriptor.Value = EvaluateDescriptorValue(result()); + ValuesMap.Add(descriptorExtension.Name, descriptorExtension.Result); } catch (Exception exception) { - descriptor.Value = new SnoopableObject(_context, exception); - } - - Descriptors.Add(descriptor); - } - - private SnoopableObject EvaluateDescriptorValue(object value) - { - var set = value as ResolveSet; - var isVariants = set != null && set.Variants.Count != 1; - var snoopableObject = new SnoopableObject(_context, value); - SnoopUtils.Redirect(snoopableObject); - - if (isVariants) - { - var type = set.Variants.Peek().Result.GetType(); - snoopableObject.Descriptor.Name = DescriptorUtils.MakeGenericTypeName(type); - snoopableObject.Descriptor.Type = snoopableObject.Descriptor.Name; + ValuesMap.Add(descriptorExtension.Name, exception); } - - return snoopableObject; } } \ No newline at end of file diff --git a/RevitLookup/Core/Metadata/DescriptorBuilder.Build.cs b/RevitLookup/Core/Metadata/DescriptorBuilder.Build.cs new file mode 100644 index 000000000..ceeba1a3f --- /dev/null +++ b/RevitLookup/Core/Metadata/DescriptorBuilder.Build.cs @@ -0,0 +1,93 @@ +// Copyright 2003-2023 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.Reflection; +using RevitLookup.Core.Objects; +using RevitLookup.Core.Utils; + +namespace RevitLookup.Core.Metadata; + +public partial class DescriptorBuilder +{ + public static IReadOnlyCollection Build(SnoopableObject snoopableObject) + { + var builder = new DescriptorBuilder(); + + switch (snoopableObject.Object) + { + case null: + return Array.Empty(); + case Type staticObjectType: + builder._obj = null; + builder._context = snoopableObject.Context; + return builder.BuildStaticObject(staticObjectType); + default: + builder._obj = snoopableObject.Object; + builder._context = snoopableObject.Context; + return builder.BuildInstanceObject(snoopableObject.Object.GetType()); + } + } + + private IReadOnlyCollection BuildInstanceObject(Type type) + { + var types = new List(); + while (type.BaseType is not null) + { + types.Add(type); + type = type.BaseType; + } + + for (var i = types.Count - 1; i >= 0; i--) + { + _type = types[i]; + _currentDescriptor = DescriptorUtils.FindSuitableDescriptor(_obj, _type); + + var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly; + if (_settings.IsStaticAllowed) flags |= BindingFlags.Static; + if (_settings.IsPrivateAllowed) flags |= BindingFlags.NonPublic; + + AddProperties(flags); + AddMethods(flags); + AddFields(flags); + AddEvents(flags); + AddExtensions(); + + _depth--; + } + + AddEnumerableItems(); + + return _descriptors; + } + + private IReadOnlyCollection BuildStaticObject(Type type) + { + _type = type; + + var flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly; + if (_settings.IsPrivateAllowed) flags |= BindingFlags.NonPublic; + + AddProperties(flags); + AddMethods(flags); + AddFields(flags); + + return _descriptors; + } +} \ No newline at end of file diff --git a/RevitLookup/Core/Enums/MemberType.cs b/RevitLookup/Core/Metadata/DescriptorBuilder.Enumeration.cs similarity index 70% rename from RevitLookup/Core/Enums/MemberType.cs rename to RevitLookup/Core/Metadata/DescriptorBuilder.Enumeration.cs index 5c4a394ee..8e6fd79da 100644 --- a/RevitLookup/Core/Enums/MemberType.cs +++ b/RevitLookup/Core/Metadata/DescriptorBuilder.Enumeration.cs @@ -18,11 +18,21 @@ // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. -namespace RevitLookup.Core.Enums; +using System.Collections; -public enum MemberType +namespace RevitLookup.Core.Metadata; + +public partial class DescriptorBuilder { - Method, - Property, - Extension + private void AddEnumerableItems() + { + if (_obj is not IEnumerable enumerable) return; + + _type = typeof(IEnumerable); + var enumerator = enumerable.GetEnumerator(); + while (enumerator.MoveNext()) + { + WriteDescriptor(enumerator.Current); + } + } } \ No newline at end of file diff --git a/RevitLookup/Core/Metadata/DescriptorBuilder.Events.cs b/RevitLookup/Core/Metadata/DescriptorBuilder.Events.cs new file mode 100644 index 000000000..3cedf6ad6 --- /dev/null +++ b/RevitLookup/Core/Metadata/DescriptorBuilder.Events.cs @@ -0,0 +1,18 @@ +using System.Reflection; +using RevitLookup.Core.Utils; + +namespace RevitLookup.Core.Metadata; + +public partial class DescriptorBuilder +{ + private void AddEvents(BindingFlags bindingFlags) + { + if (!_settings.IsEventsAllowed) return; + + var members = _type.GetEvents(bindingFlags); + foreach (var member in members) + { + WriteDescriptor(member, DescriptorUtils.MakeGenericTypeName(member.EventHandlerType), null); + } + } +} \ No newline at end of file diff --git a/RevitLookup/Core/Metadata/DescriptorBuilder.Extensions.cs b/RevitLookup/Core/Metadata/DescriptorBuilder.Extensions.cs new file mode 100644 index 000000000..7d71cf15f --- /dev/null +++ b/RevitLookup/Core/Metadata/DescriptorBuilder.Extensions.cs @@ -0,0 +1,41 @@ +// Copyright 2003-2023 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 RevitLookup.Core.Contracts; +using RevitLookup.Core.Extensions; + +namespace RevitLookup.Core.Metadata; + +public partial class DescriptorBuilder +{ + private void AddExtensions() + { + if (!_settings.IsExtensionsAllowed) return; + if (_currentDescriptor is not IDescriptorExtension extension) return; + + var manager = new ExtensionManager(_context); + extension.RegisterExtensions(manager); + + foreach (var pair in manager.ValuesMap) + { + WriteDescriptor(pair.Key, pair.Value); + } + } +} \ No newline at end of file diff --git a/RevitLookup/Core/Metadata/DescriptorBuilder.Fields.cs b/RevitLookup/Core/Metadata/DescriptorBuilder.Fields.cs new file mode 100644 index 000000000..f852bf09a --- /dev/null +++ b/RevitLookup/Core/Metadata/DescriptorBuilder.Fields.cs @@ -0,0 +1,38 @@ +// Copyright 2003-2023 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.Reflection; + +namespace RevitLookup.Core.Metadata; + +public partial class DescriptorBuilder +{ + private void AddFields(BindingFlags bindingFlags) + { + if (!_settings.IsFieldsAllowed) return; + + var members = _type.GetFields(bindingFlags); + foreach (var member in members) + { + if (member.IsSpecialName) continue; + WriteDescriptor(member, member.GetValue(_obj), null); + } + } +} \ No newline at end of file diff --git a/RevitLookup/Core/Metadata/DescriptorBuilder.Methods.cs b/RevitLookup/Core/Metadata/DescriptorBuilder.Methods.cs new file mode 100644 index 000000000..101e9961d --- /dev/null +++ b/RevitLookup/Core/Metadata/DescriptorBuilder.Methods.cs @@ -0,0 +1,79 @@ +// Copyright 2003-2023 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.Reflection; +using RevitLookup.Core.Contracts; + +namespace RevitLookup.Core.Metadata; + +public partial class DescriptorBuilder +{ + private void AddMethods(BindingFlags bindingFlags) + { + var members = _type.GetMethods(bindingFlags); + foreach (var member in members) + { + if (member.IsSpecialName) continue; + + object value; + ParameterInfo[] parameters = null; + try + { + if (!TryEvaluate(member, out value, out parameters)) continue; + } + catch (Exception exception) + { + value = exception; + } + + WriteDescriptor(member, value, parameters); + } + } + + private bool TryEvaluate(MethodInfo member, out object value, out ParameterInfo[] parameters) + { + value = null; + parameters = member.GetParameters(); + if (member.ReturnType.Name == "Void") + { + if (!_settings.IsUnsupportedAllowed) return false; + + value = new NotSupportedException("Method doesn't return a value"); + return true; + } + + if (_currentDescriptor is IDescriptorResolver resolver) + { + value = resolver.Resolve(_context, member.Name, parameters); + if (value is not null) return true; + } + + if (parameters.Length > 0) + { + if (!_settings.IsUnsupportedAllowed) return false; + + value = new NotSupportedException("Unsupported method overload"); + return true; + } + + value = member.Invoke(_obj, null); + return true; + } +} \ No newline at end of file diff --git a/RevitLookup/Core/Metadata/DescriptorBuilder.Properties.cs b/RevitLookup/Core/Metadata/DescriptorBuilder.Properties.cs new file mode 100644 index 000000000..63a79a4d3 --- /dev/null +++ b/RevitLookup/Core/Metadata/DescriptorBuilder.Properties.cs @@ -0,0 +1,79 @@ +// Copyright 2003-2023 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.Reflection; +using RevitLookup.Core.Contracts; + +namespace RevitLookup.Core.Metadata; + +public partial class DescriptorBuilder +{ + private void AddProperties(BindingFlags bindingFlags) + { + var members = _type.GetProperties(bindingFlags); + foreach (var member in members) + { + if (member.IsSpecialName) continue; + + object value; + ParameterInfo[] parameters = null; + try + { + if (!TryEvaluate(member, out value, out parameters)) continue; + } + catch (Exception exception) + { + value = exception; + } + + WriteDescriptor(member, value, parameters); + } + } + + private bool TryEvaluate(PropertyInfo member, out object value, out ParameterInfo[] parameters) + { + value = null; + parameters = null; + + if (!member.CanRead) + { + value = new NotSupportedException("Property does not have a get accessor, it cannot be read"); + return true; + } + + parameters = member.GetMethod.GetParameters(); + if (_currentDescriptor is IDescriptorResolver resolver) + { + value = resolver.Resolve(_context, member.Name, parameters); + if (value is not null) return true; + } + + if (parameters.Length > 0) + { + if (!_settings.IsUnsupportedAllowed) return false; + + value = new NotSupportedException("Unsupported property overload"); + return true; + } + + value = member.GetValue(_obj); + return true; + } +} \ No newline at end of file diff --git a/RevitLookup/Core/Metadata/DescriptorBuilder.cs b/RevitLookup/Core/Metadata/DescriptorBuilder.cs new file mode 100644 index 000000000..42b516ebf --- /dev/null +++ b/RevitLookup/Core/Metadata/DescriptorBuilder.cs @@ -0,0 +1,171 @@ +// Copyright 2003-2023 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.Reflection; +using Autodesk.Revit.DB; +using RevitLookup.Core.ComponentModel.Descriptors; +using RevitLookup.Core.Enums; +using RevitLookup.Core.Objects; +using RevitLookup.Core.Utils; +using RevitLookup.Services.Contracts; + +namespace RevitLookup.Core.Metadata; + +public partial class DescriptorBuilder +{ + private readonly List _descriptors; + private readonly ISettingsService _settings; + private Descriptor _currentDescriptor; + private Document _context; + private object _obj; + private Type _type; + private int _depth; + + private DescriptorBuilder() + { + _descriptors = new List(16); + _settings = Host.GetService(); + } + + private void WriteDescriptor(object value) + { + var descriptor = new ObjectDescriptor + { + Depth = _depth, + Value = EvaluateValue(value), + TypeFullName = _type.FullName, + MemberAttributes = MemberAttributes.Property, + Type = DescriptorUtils.MakeGenericTypeName(_type) + }; + + descriptor.Name = descriptor.Value.Descriptor.Type; + + _descriptors.Add(descriptor); + } + + private void WriteDescriptor(string name, object value) + { + var descriptor = new ObjectDescriptor + { + Depth = _depth, + Name = name, + Value = EvaluateValue(value), + TypeFullName = _type.FullName, + MemberAttributes = MemberAttributes.Extension, + Type = DescriptorUtils.MakeGenericTypeName(_type) + }; + + _descriptors.Add(descriptor); + } + + private void WriteDescriptor(MemberInfo member, object value, ParameterInfo[] parameters) + { + var descriptor = new ObjectDescriptor + { + Depth = _depth, + TypeFullName = _type.FullName, + Value = EvaluateValue(member, value), + Name = EvaluateName(member, parameters), + MemberAttributes = EvaluateAttributes(member), + Type = DescriptorUtils.MakeGenericTypeName(_type) + }; + + _descriptors.Add(descriptor); + } + + private SnoopableObject EvaluateValue(MemberInfo member, object value) + { + var snoopableObject = new SnoopableObject(_context, value); + SnoopUtils.Redirect(member.Name, snoopableObject); + RestoreSetDescription(member, value, snoopableObject); + return snoopableObject; + } + + private SnoopableObject EvaluateValue(object value) + { + var snoopableObject = new SnoopableObject(_context, value); + SnoopUtils.Redirect(snoopableObject); + RestoreSetDescription(value, snoopableObject); + return snoopableObject; + } + + private static string EvaluateName(MemberInfo member, [CanBeNull] ParameterInfo[] types) + { + if (types is null) return member.Name; + if (types.Length == 0) return member.Name; + + var parameterNames = types.Select(info => DescriptorUtils.MakeGenericTypeName(info.ParameterType)); + var parameters = string.Join(", ", parameterNames); + return $"{member.Name} ({parameters})"; + } + + private static MemberAttributes EvaluateAttributes(MemberInfo member) + { + return member switch + { + MethodInfo info => GetModifiers(MemberAttributes.Method, info.Attributes), + PropertyInfo info => GetModifiers(MemberAttributes.Property, info.CanRead ? info.GetMethod.Attributes : info.SetMethod.Attributes), + FieldInfo info => GetModifiers(MemberAttributes.Field, info.Attributes), + EventInfo info => GetModifiers(MemberAttributes.Event, info.AddMethod.Attributes), + _ => throw new ArgumentOutOfRangeException(nameof(member)) + }; + } + + private static MemberAttributes GetModifiers(MemberAttributes attributes, MethodAttributes methodAttributes) + { + if ((methodAttributes & MethodAttributes.Static) != 0) attributes |= MemberAttributes.Static; + if ((methodAttributes & MethodAttributes.Private) != 0) attributes |= MemberAttributes.Private; + return attributes; + } + + private static MemberAttributes GetModifiers(MemberAttributes attributes, FieldAttributes fieldAttributes) + { + if ((fieldAttributes & FieldAttributes.Static) != 0) attributes |= MemberAttributes.Static; + if ((fieldAttributes & FieldAttributes.Private) != 0) attributes |= MemberAttributes.Private; + return attributes; + } + + private static void RestoreSetDescription(object value, SnoopableObject snoopableObject) + { + if (value is not ResolveSet set) return; + if (set.Variants.Count == 1) return; + + var type = set.Variants.Peek().Result.GetType(); + var name = DescriptorUtils.MakeGenericTypeName(type); + snoopableObject.Descriptor.Name = name; + snoopableObject.Descriptor.Type = name; + } + + private static void RestoreSetDescription(MemberInfo member, object value, SnoopableObject snoopableObject) + { + if (value is not ResolveSet set) return; + if (set.Variants.Count == 1) return; + + var name = member switch + { + PropertyInfo property => DescriptorUtils.MakeGenericTypeName(property.GetMethod.ReturnType), + MethodInfo method => DescriptorUtils.MakeGenericTypeName(method.ReturnType), + _ => snoopableObject.Descriptor.Name + }; + + snoopableObject.Descriptor.Name = name; + snoopableObject.Descriptor.Type = name; + } +} \ No newline at end of file diff --git a/RevitLookup/Core/Objects/Descriptor.cs b/RevitLookup/Core/Objects/Descriptor.cs index bdadd137e..4fefc1bbf 100644 --- a/RevitLookup/Core/Objects/Descriptor.cs +++ b/RevitLookup/Core/Objects/Descriptor.cs @@ -22,29 +22,13 @@ namespace RevitLookup.Core.Objects; -public abstract class Descriptor : IComparable, IComparable +public abstract class Descriptor { + public int Depth { get; set; } public string TypeFullName { get; set; } public string Type { get; set; } public string Name { get; set; } public string Description { get; set; } - public MemberType MemberType { get; set; } public MemberAttributes MemberAttributes { get; set; } public SnoopableObject Value { get; set; } - - public int CompareTo(object obj) - { - if (ReferenceEquals(null, obj)) return 1; - if (ReferenceEquals(this, obj)) return 0; - return obj is Descriptor other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(Descriptor)}"); - } - - public int CompareTo(Descriptor other) - { - if (ReferenceEquals(this, other)) return 0; - if (ReferenceEquals(null, other)) return 1; - var typeComparison = string.Compare(Type, other.Type, StringComparison.Ordinal); - if (typeComparison != 0) return typeComparison; - return string.Compare(Name, other.Name, StringComparison.Ordinal); - } } \ No newline at end of file diff --git a/RevitLookup/Core/Objects/SnoopableObject.cs b/RevitLookup/Core/Objects/SnoopableObject.cs index 4ebb9b30b..ec6e83d17 100644 --- a/RevitLookup/Core/Objects/SnoopableObject.cs +++ b/RevitLookup/Core/Objects/SnoopableObject.cs @@ -20,6 +20,7 @@ // (Rights in Technical Data and Computer Software), as applicable. using Autodesk.Revit.DB; +using RevitLookup.Core.Metadata; using RevitLookup.Core.Utils; namespace RevitLookup.Core.Objects; @@ -47,12 +48,12 @@ public SnoopableObject(Document context, object obj) public IReadOnlyCollection GetMembers() { - return _members = new DescriptorBuilder(this).Build(); + return _members = DescriptorBuilder.Build(this); } public async Task> GetMembersAsync() { - return _members = await Application.ExternalDescriptorHandler.RaiseAsync(_ => new DescriptorBuilder(this).Build()); + return _members = await Application.ExternalDescriptorHandler.RaiseAsync(_ => DescriptorBuilder.Build(this)); } public async Task> GetCachedMembersAsync() diff --git a/RevitLookup/Core/Utils/DescriptorBuilder.cs b/RevitLookup/Core/Utils/DescriptorBuilder.cs deleted file mode 100644 index 79f9b7df6..000000000 --- a/RevitLookup/Core/Utils/DescriptorBuilder.cs +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2003-2023 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; -using System.Reflection; -using RevitLookup.Core.ComponentModel.Descriptors; -using RevitLookup.Core.Contracts; -using RevitLookup.Core.Enums; -using RevitLookup.Core.Extensions; -using RevitLookup.Core.Objects; -using RevitLookup.Services.Contracts; - -namespace RevitLookup.Core.Utils; - -public sealed class DescriptorBuilder -{ - private readonly List _descriptors; - private readonly ISettingsService _settings; - private readonly SnoopableObject _snoopableObject; - [CanBeNull] private Descriptor _currentDescriptor; - private Type _type; - - public DescriptorBuilder(SnoopableObject snoopableObject) - { - _snoopableObject = snoopableObject; - _descriptors = new List(16); - _settings = Host.GetService(); - } - - public IReadOnlyCollection Build() - { - return _snoopableObject.Object switch - { - null => Array.Empty(), - Type staticObjectType => BuildStaticObject(staticObjectType), - _ => BuildInstanceObject(_snoopableObject.Object.GetType()) - }; - } - - private IReadOnlyCollection BuildInstanceObject(Type type) - { - var types = new List(); - while (type.BaseType is not null) - { - types.Add(type); - type = type.BaseType; - } - - for (var i = types.Count - 1; i >= 0; i--) - { - _type = types[i]; - - //Finding a descriptor to analyze IDescriptorResolver and IDescriptorExtension interfaces - _currentDescriptor = DescriptorUtils.FindSuitableDescriptor(_snoopableObject.Object, _type); - - AddProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); - AddMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); - } - - AddEnumerableItems(); - return _descriptors; - } - - private IReadOnlyCollection BuildStaticObject(Type staticObjectType) - { - _type = staticObjectType; - _snoopableObject.Object = null; - AddProperties(BindingFlags.Public | BindingFlags.Static); - AddMethods(BindingFlags.Public | BindingFlags.Static); - return _descriptors; - } - - private void AddProperties(BindingFlags bindingFlags) - { - var members = _type.GetProperties(bindingFlags); - var descriptors = new List(members.Length); - - foreach (var member in members) - { - if (member.IsSpecialName) continue; - - object value; - ParameterInfo[] parameters = null; - try - { - if (!TryEvaluate(member, out value, out parameters)) continue; - } - catch (Exception exception) - { - value = exception; - } - - var descriptor = CreateDescriptor(member, value, parameters); - descriptors.Add(descriptor); - } - - ApplyGroupCollector(descriptors); - } - - private void AddMethods(BindingFlags bindingFlags) - { - var members = _type.GetMethods(bindingFlags); - var descriptors = new List(members.Length); - - foreach (var member in members) - { - if (member.IsSpecialName) continue; - - object value; - ParameterInfo[] parameters = null; - try - { - if (!TryEvaluate(member, out value, out parameters)) continue; - } - catch (Exception exception) - { - value = exception; - } - - var descriptor = CreateDescriptor(member, value, parameters); - descriptors.Add(descriptor); - } - - AddExtensions(descriptors); - ApplyGroupCollector(descriptors); - } - - private void AddExtensions(List descriptors) - { - if (!_settings.IsExtensionsAllowed) return; - if (_currentDescriptor is not IDescriptorExtension extension) return; - - var manager = new ExtensionManager(_snoopableObject.Context, _currentDescriptor); - extension.RegisterExtensions(manager); - - descriptors.AddRange(manager.Descriptors); - } - - private void AddEnumerableItems() - { - if (_snoopableObject.Object is not IEnumerable enumerable) return; - - var enumerator = enumerable.GetEnumerator(); - while (enumerator.MoveNext()) - { - var enumerableDescriptor = new ObjectDescriptor - { - Type = nameof(IEnumerable), - Value = new SnoopableObject(_snoopableObject.Context, enumerator) - }; - - SnoopUtils.Redirect(enumerableDescriptor.Value); - enumerableDescriptor.Name = enumerableDescriptor.Value.Descriptor.Type; - _descriptors.Add(enumerableDescriptor); - } - } - - private bool TryEvaluate(PropertyInfo member, out object value, out ParameterInfo[] parameters) - { - value = null; - parameters = null; - - if (!member.CanRead) - { - value = new NotSupportedException("Property does not have a get accessor, it cannot be read"); - return true; - } - - parameters = member.GetMethod.GetParameters(); - if (_currentDescriptor is IDescriptorResolver resolver) - { - value = resolver.Resolve(_snoopableObject.Context, member.Name, parameters); - if (value is not null) return true; - } - - if (parameters.Length > 0) - { - if (!_settings.IsUnsupportedAllowed) return false; - - value = new NotSupportedException("Unsupported property overload"); - return true; - } - - value = member.GetValue(_snoopableObject.Object); - return true; - } - - private bool TryEvaluate(MethodInfo member, out object value, out ParameterInfo[] parameters) - { - value = null; - parameters = member.GetParameters(); - if (member.ReturnType.Name == "Void") - { - if (!_settings.IsUnsupportedAllowed) return false; - - value = new NotSupportedException("Method doesn't return a value"); - return true; - } - - if (_currentDescriptor is IDescriptorResolver resolver) - { - value = resolver.Resolve(_snoopableObject.Context, member.Name, parameters); - if (value is not null) return true; - } - - if (parameters.Length > 0) - { - if (!_settings.IsUnsupportedAllowed) return false; - - value = new NotSupportedException("Unsupported method overload"); - return true; - } - - value = member.Invoke(_snoopableObject.Object, null); - return true; - } - - private void ApplyGroupCollector(List descriptors) - { - descriptors.Sort(); - _descriptors.AddRange(descriptors); - } - - private ObjectDescriptor CreateDescriptor(MemberInfo member, object value, ParameterInfo[] parameters) - { - var descriptor = new ObjectDescriptor - { - TypeFullName = member.ReflectedType!.FullName, - Type = DescriptorUtils.MakeGenericTypeName(_type), - Name = EvaluateDescriptorName(member, parameters), - Value = EvaluateDescriptorValue(member, value), - }; - - switch (member) - { - case PropertyInfo info: - descriptor.MemberType = MemberType.Property; - if (!info.CanRead) break; - - SetAttributes(info.CanRead ? info.GetMethod.Attributes : info.SetMethod.Attributes); - break; - case MethodInfo info: - descriptor.MemberType = MemberType.Method; - SetAttributes(info.Attributes); - break; - default: - descriptor.MemberType = MemberType.Method; - break; - } - - void SetAttributes(MethodAttributes attributes) - { - if ((attributes & MethodAttributes.Static) != 0) - { - descriptor.MemberAttributes |= MemberAttributes.Static; - } - - if ((attributes & MethodAttributes.Private) != 0) - { - descriptor.MemberAttributes |= MemberAttributes.Private; - } - } - - return descriptor; - } - - private SnoopableObject EvaluateDescriptorValue(MemberInfo member, object value) - { - var isVariants = value is ResolveSet set && set.Variants.Count != 1; - var snoopableObject = new SnoopableObject(_snoopableObject.Context, value); - SnoopUtils.Redirect(member.Name, snoopableObject); - - if (isVariants) - { - snoopableObject.Descriptor.Name = member switch - { - PropertyInfo property => DescriptorUtils.MakeGenericTypeName(property.GetMethod.ReturnType), - MethodInfo method => DescriptorUtils.MakeGenericTypeName(method.ReturnType), - _ => snoopableObject.Descriptor.Name - }; - - // snoopableObject.Descriptor.TypeFullName = $"{member.ReflectedType!.FullName}"; - snoopableObject.Descriptor.Type = snoopableObject.Descriptor.Name; - } - - return snoopableObject; - } - - private static string EvaluateDescriptorName(MemberInfo member, ParameterInfo[] parameters) - { - if (parameters is null || parameters.Length == 0) return member.Name; - - return $"{member.Name} ({string.Join(", ", parameters.Select(info => DescriptorUtils.MakeGenericTypeName(info.ParameterType)))})"; - } -} \ No newline at end of file diff --git a/RevitLookup/RibbonController.cs b/RevitLookup/RibbonController.cs index 60def2630..db6c9a79e 100644 --- a/RevitLookup/RibbonController.cs +++ b/RevitLookup/RibbonController.cs @@ -69,7 +69,6 @@ private static void ResolveSelectionButton(ISettingsService settingsService, Pul public static void ReloadPanels(ISettingsService settingsService) { - //Synchronising the execution context Application.ActionEventHandler.Raise(_ => { RibbonUtils.RemovePanel("CustomCtrl_%CustomCtrl_%Add-Ins%Revit Lookup%RevitLookupButton", PanelName); diff --git a/RevitLookup/Services/Contracts/ISettingsService.cs b/RevitLookup/Services/Contracts/ISettingsService.cs index 23eb21b79..8c47f06c4 100644 --- a/RevitLookup/Services/Contracts/ISettingsService.cs +++ b/RevitLookup/Services/Contracts/ISettingsService.cs @@ -28,10 +28,14 @@ public interface ISettingsService ThemeType Theme { get; set; } WindowBackdropType Background { get; set; } int TransitionDuration { get; } - bool IsExtensionsAllowed { get; set; } - bool IsUnsupportedAllowed { get; set; } - bool IsModifyTabAllowed { get; set; } bool IsHardwareRenderingAllowed { get; set; } + bool IsModifyTabAllowed { get; set; } + bool IsUnsupportedAllowed { get; set; } + bool IsPrivateAllowed { get; set; } + bool IsStaticAllowed { get; set; } + bool IsFieldsAllowed { get; set; } + bool IsEventsAllowed { get; set; } + bool IsExtensionsAllowed { get; set; } int ApplyTransition(bool value); void Save(); } \ No newline at end of file diff --git a/RevitLookup/Services/SettingsService.cs b/RevitLookup/Services/SettingsService.cs index 0cb4976ff..558bfd866 100644 --- a/RevitLookup/Services/SettingsService.cs +++ b/RevitLookup/Services/SettingsService.cs @@ -36,16 +36,20 @@ internal sealed class Settings { public ThemeType Theme { get; set; } = ThemeType.Light; public WindowBackdropType Background { get; set; } = WindowBackdropType.None; - public int TransitionDuration { get; set; } // = SettingsService.DefaultTransitionDuration; - public bool IsExtensionsAllowed { get; set; } - public bool IsUnsupportedAllowed { get; set; } - public bool IsModifyTabAllowed { get; set; } + public int TransitionDuration { get; set; } //= SettingsService.DefaultTransitionDuration; public bool IsHardwareRenderingAllowed { get; set; } = true; + public bool IsModifyTabAllowed { get; set; } + public bool IsUnsupportedAllowed { get; set; } + public bool IsPrivateAllowed { get; set; } + public bool IsStaticAllowed { get; set; } + public bool IsFieldsAllowed { get; set; } + public bool IsEventsAllowed { get; set; } + public bool IsExtensionsAllowed { get; set; } } public sealed class SettingsService : ISettingsService { - private const int DefaultTransitionDuration = 200; + public const int DefaultTransitionDuration = 200; private readonly Settings _settings; private readonly string _settingsFile; @@ -73,10 +77,16 @@ public int TransitionDuration private set => _settings.TransitionDuration = value; } - public bool IsExtensionsAllowed + public bool IsHardwareRenderingAllowed { - get => _settings.IsExtensionsAllowed; - set => _settings.IsExtensionsAllowed = value; + get => _settings.IsHardwareRenderingAllowed; + set => _settings.IsHardwareRenderingAllowed = value; + } + + public bool IsModifyTabAllowed + { + get => _settings.IsModifyTabAllowed; + set => _settings.IsModifyTabAllowed = value; } public bool IsUnsupportedAllowed @@ -85,16 +95,34 @@ public bool IsUnsupportedAllowed set => _settings.IsUnsupportedAllowed = value; } - public bool IsModifyTabAllowed + public bool IsPrivateAllowed { - get => _settings.IsModifyTabAllowed; - set => _settings.IsModifyTabAllowed = value; + get => _settings.IsPrivateAllowed; + set => _settings.IsPrivateAllowed = value; } - public bool IsHardwareRenderingAllowed + public bool IsStaticAllowed { - get => _settings.IsHardwareRenderingAllowed; - set => _settings.IsHardwareRenderingAllowed = value; + get => _settings.IsStaticAllowed; + set => _settings.IsStaticAllowed = value; + } + + public bool IsFieldsAllowed + { + get => _settings.IsFieldsAllowed; + set => _settings.IsFieldsAllowed = value; + } + + public bool IsEventsAllowed + { + get => _settings.IsEventsAllowed; + set => _settings.IsEventsAllowed = value; + } + + public bool IsExtensionsAllowed + { + get => _settings.IsExtensionsAllowed; + set => _settings.IsExtensionsAllowed = value; } public int ApplyTransition(bool value) @@ -126,7 +154,7 @@ private Settings LoadSettings() try { - var config = File.ReadAllText(_settingsFile); + using var config = File.OpenRead(_settingsFile); var jsonSerializerOptions = new JsonSerializerOptions { Converters = @@ -134,8 +162,8 @@ private Settings LoadSettings() new JsonStringEnumConverter() } }; - var json = JsonSerializer.Deserialize(config, jsonSerializerOptions); - return json; + + return JsonSerializer.Deserialize(config, jsonSerializerOptions); } catch { diff --git a/RevitLookup/ViewModels/Dialogs/SearchElementsViewModel.cs b/RevitLookup/ViewModels/Dialogs/SearchElementsViewModel.cs index 06a627357..46edd5860 100644 --- a/RevitLookup/ViewModels/Dialogs/SearchElementsViewModel.cs +++ b/RevitLookup/ViewModels/Dialogs/SearchElementsViewModel.cs @@ -41,7 +41,7 @@ public bool SearchIds(ISnoopService snoopService) { var delimiter = delimiters[i]; var split = row.Split(new[] {delimiter}, StringSplitOptions.RemoveEmptyEntries); - if (split.Length > 1 || i == delimiters.Length - 1 || (split.Length == 1 && split[0] != row)) + if (split.Length > 1 || i == delimiters.Length - 1 || split.Length == 1 && split[0] != row) { items.AddRange(split); break; diff --git a/RevitLookup/ViewModels/Pages/SettingsViewModel.cs b/RevitLookup/ViewModels/Pages/SettingsViewModel.cs index 2ffbe9c6a..51250f0dd 100644 --- a/RevitLookup/ViewModels/Pages/SettingsViewModel.cs +++ b/RevitLookup/ViewModels/Pages/SettingsViewModel.cs @@ -18,8 +18,6 @@ // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. -using System.Windows.Interop; -using System.Windows.Media; using CommunityToolkit.Mvvm.ComponentModel; using RevitLookup.Services.Contracts; using Wpf.Ui.Appearance; @@ -35,13 +33,17 @@ public sealed partial class SettingsViewModel : ObservableObject private readonly INavigationService _navigationService; private readonly ISettingsService _settingsService; private readonly ISnackbarService _snackbarService; + [ObservableProperty] private ThemeType _theme; [ObservableProperty] private WindowBackdropType _background; - [ObservableProperty] private bool _isExtensionsAllowed; + [ObservableProperty] private bool _isSmoothEnabled; [ObservableProperty] private bool _isHardwareRenderingAllowed; [ObservableProperty] private bool _isModifyTabAllowed; - [ObservableProperty] private bool _isSmoothEnabled; [ObservableProperty] private bool _isUnsupportedAllowed; - [ObservableProperty] private ThemeType _theme; + [ObservableProperty] private bool _isPrivateAllowed; + [ObservableProperty] private bool _isStaticAllowed; + [ObservableProperty] private bool _isFieldsAllowed; + [ObservableProperty] private bool _isEventsAllowed; + [ObservableProperty] private bool _isExtensionsAllowed; public SettingsViewModel(ISettingsService settingsService, INavigationService navigationService, ISnackbarService snackbarService) { @@ -51,10 +53,14 @@ public SettingsViewModel(ISettingsService settingsService, INavigationService na _theme = settingsService.Theme; _background = settingsService.Background; _isSmoothEnabled = settingsService.TransitionDuration > 0; + _isHardwareRenderingAllowed = settingsService.IsHardwareRenderingAllowed; + _isModifyTabAllowed = settingsService.IsModifyTabAllowed; _isUnsupportedAllowed = settingsService.IsUnsupportedAllowed; + _isPrivateAllowed = settingsService.IsPrivateAllowed; + _isStaticAllowed = settingsService.IsStaticAllowed; + _isFieldsAllowed = settingsService.IsFieldsAllowed; + _isEventsAllowed = settingsService.IsEventsAllowed; _isExtensionsAllowed = settingsService.IsExtensionsAllowed; - _isModifyTabAllowed = settingsService.IsModifyTabAllowed; - _isHardwareRenderingAllowed = settingsService.IsHardwareRenderingAllowed; } public List Themes { get; } = new() @@ -88,25 +94,46 @@ partial void OnIsSmoothEnabledChanged(bool value) _navigationService.GetNavigationControl().TransitionDuration = transitionDuration; } + partial void OnIsHardwareRenderingAllowedChanged(bool value) + { + _settingsService.IsHardwareRenderingAllowed = value; + if (value) Application.EnableHardwareRendering(_settingsService); + else Application.DisableHardwareRendering(_settingsService); + } + + partial void OnIsModifyTabAllowedChanged(bool value) + { + _settingsService.IsModifyTabAllowed = value; + RibbonController.ReloadPanels(_settingsService); + } + partial void OnIsUnsupportedAllowedChanged(bool value) { _settingsService.IsUnsupportedAllowed = value; } - partial void OnIsExtensionsAllowedChanged(bool value) + partial void OnIsPrivateAllowedChanged(bool value) { - _settingsService.IsExtensionsAllowed = value; + _settingsService.IsPrivateAllowed = value; } - partial void OnIsModifyTabAllowedChanged(bool value) + partial void OnIsStaticAllowedChanged(bool value) { - _settingsService.IsModifyTabAllowed = value; - RibbonController.ReloadPanels(_settingsService); + _settingsService.IsStaticAllowed = value; } - partial void OnIsHardwareRenderingAllowedChanged(bool value) + partial void OnIsFieldsAllowedChanged(bool value) { - _settingsService.IsModifyTabAllowed = value; - RenderOptions.ProcessRenderMode = value ? RenderMode.Default : RenderMode.SoftwareOnly; + _settingsService.IsFieldsAllowed = value; + } + + partial void OnIsEventsAllowedChanged(bool value) + { + _settingsService.IsEventsAllowed = value; + } + + partial void OnIsExtensionsAllowedChanged(bool value) + { + _settingsService.IsExtensionsAllowed = value; } } \ No newline at end of file diff --git a/RevitLookup/ViewModels/Utils/SearchEngine.cs b/RevitLookup/ViewModels/Utils/SearchEngine.cs index 354df44c1..f950ce861 100644 --- a/RevitLookup/ViewModels/Utils/SearchEngine.cs +++ b/RevitLookup/ViewModels/Utils/SearchEngine.cs @@ -68,7 +68,7 @@ private static SearchResults Search(ISnoopViewModel model, SearchOption option) }; //Display unfiltered data if object greater than 1 or single object - if (objectsCount > 1 || (objectsCount == 1 && model.SnoopableObjects.Count > 1)) + if (objectsCount > 1 || objectsCount == 1 && model.SnoopableObjects.Count > 1) return new SearchResults { Objects = filteredObjects, @@ -87,7 +87,7 @@ private static SearchResults Search(ISnoopViewModel model, SearchOption option) var filteredObjects = Search(model.SearchText, model.SnoopableObjects); //Display unfiltered data if object greater than 1 or single object - if (filteredObjects.Count > 1 || (filteredObjects.Count == 1 && model.SnoopableObjects.Count > 1)) + if (filteredObjects.Count > 1 || filteredObjects.Count == 1 && model.SnoopableObjects.Count > 1) return new SearchResults { Data = model.SnoopableData @@ -131,7 +131,8 @@ private static List Search(string query, IEnumerable Search(string query, IEnumerable dat var filteredSnoopableData = new List(); foreach (var item in data) if (item.Name.Contains(query, StringComparison.OrdinalIgnoreCase)) filteredSnoopableData.Add(item); - else if (item.Value.Descriptor.Name.Contains(query, StringComparison.OrdinalIgnoreCase)) filteredSnoopableData.Add(item); + else if (item.Value.Descriptor.Name.Contains(query, StringComparison.OrdinalIgnoreCase)) + filteredSnoopableData.Add(item); return filteredSnoopableData; } diff --git a/RevitLookup/Views/Converters/DescriptorConverters.cs b/RevitLookup/Views/Converters/DescriptorConverters.cs new file mode 100644 index 000000000..8e23530c6 --- /dev/null +++ b/RevitLookup/Views/Converters/DescriptorConverters.cs @@ -0,0 +1,164 @@ +// Copyright 2003-2023 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.Diagnostics; +using System.Globalization; +using System.Windows.Data; +using System.Windows.Markup; +using RevitLookup.Core.ComponentModel.Descriptors; +using RevitLookup.Core.Contracts; +using RevitLookup.Core.Enums; +using RevitLookup.Core.Objects; +using Wpf.Ui.Common; + +namespace RevitLookup.Views.Converters; + +public abstract class DescriptorConverter : MarkupExtension, IValueConverter +{ + public abstract object Convert(object value, Type targetType, object parameter, CultureInfo culture); + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotSupportedException(); + } + + protected static string CreateCombinedName(Descriptor descriptor) + { + if (string.IsNullOrEmpty(descriptor.Name)) return descriptor.Name; + return string.IsNullOrEmpty(descriptor.Description) ? descriptor.Name : $"{descriptor.Description}: {descriptor.Name}"; + } + + protected static string CreateSingleName(Descriptor descriptor) + { + if (string.IsNullOrEmpty(descriptor.Name)) return descriptor.Name; + return string.IsNullOrEmpty(descriptor.Description) ? descriptor.Name : descriptor.Description; + } + + protected string ConvertInvalidNames(string text) + { + return text switch + { + null => "", + "" => "", + _ => text + }; + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return this; + } +} + +public sealed class SingleDescriptorConverter : DescriptorConverter +{ + public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return ConvertInvalidNames(CreateSingleName((Descriptor) value!)); + } +} + +public sealed class CombinedDescriptorConverter : DescriptorConverter +{ + public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return ConvertInvalidNames(CreateCombinedName((Descriptor) value!)); + } +} + +public sealed class HandledDescriptorConverter : MarkupExtension, IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var descriptor = (Descriptor) value!; + if (descriptor is IDescriptorEnumerator enumerator) return !enumerator.IsEmpty; + return descriptor is IDescriptorCollector; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotSupportedException(); + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return this; + } +} + +public sealed class ExceptionDescriptorConverter : MarkupExtension, IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var descriptor = (Descriptor) value!; + return descriptor is ExceptionDescriptor; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotSupportedException(); + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return this; + } +} + +public sealed class IconDescriptorConverter : MarkupExtension, IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var attributes = (MemberAttributes) value!; + + if ((attributes & MemberAttributes.Property) != 0 && (attributes & MemberAttributes.Private) != 0 && (attributes & MemberAttributes.Static) != 0) return SymbolRegular.CalendarLock16; + if ((attributes & MemberAttributes.Property) != 0 && (attributes & MemberAttributes.Private) != 0) return SymbolRegular.DocumentLock16; + if ((attributes & MemberAttributes.Property) != 0 && (attributes & MemberAttributes.Static) != 0) return SymbolRegular.ClipboardNote16; + if ((attributes & MemberAttributes.Property) != 0) return SymbolRegular.ClipboardBulletListLtr16; + + if ((attributes & MemberAttributes.Method) != 0 && (attributes & MemberAttributes.Private) != 0 && (attributes & MemberAttributes.Static) != 0) return SymbolRegular.ShieldLock16; + if ((attributes & MemberAttributes.Method) != 0 && (attributes & MemberAttributes.Private) != 0) return SymbolRegular.TableLock16; + if ((attributes & MemberAttributes.Method) != 0 && (attributes & MemberAttributes.Static) != 0) return SymbolRegular.Box16; + if ((attributes & MemberAttributes.Method) != 0) return SymbolRegular.Cube16; + + if ((attributes & MemberAttributes.Field) != 0 && (attributes & MemberAttributes.Private) != 0 && (attributes & MemberAttributes.Static) != 0) return SymbolRegular.TrophyLock16; + if ((attributes & MemberAttributes.Field) != 0 && (attributes & MemberAttributes.Private) != 0) return SymbolRegular.TagLock16; + if ((attributes & MemberAttributes.Field) != 0 && (attributes & MemberAttributes.Static) != 0) return SymbolRegular.TagMultiple16; + if ((attributes & MemberAttributes.Field) != 0) return SymbolRegular.Tag16; + + if ((attributes & MemberAttributes.Event) != 0 && (attributes & MemberAttributes.Private) != 0) return SymbolRegular.FlashSettings20; + if ((attributes & MemberAttributes.Event) != 0) return SymbolRegular.Flash16; + + if ((attributes & MemberAttributes.Extension) != 0) return SymbolRegular.CubeArrowCurveDown20; + + Debug.Assert(false, "Unsupported image"); + return Binding.DoNothing; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotSupportedException(); + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return this; + } +} \ No newline at end of file diff --git a/RevitLookup/Views/Converters/TreeViewSourceConverter.cs b/RevitLookup/Views/Converters/TreeViewSourceConverter.cs index 790af4da8..35657edc0 100644 --- a/RevitLookup/Views/Converters/TreeViewSourceConverter.cs +++ b/RevitLookup/Views/Converters/TreeViewSourceConverter.cs @@ -22,6 +22,7 @@ using System.Globalization; using System.Windows.Data; using System.Windows.Markup; +using RevitLookup.Core.Objects; namespace RevitLookup.Views.Converters; @@ -34,10 +35,10 @@ public object Convert(object value, Type targetType, object parameter, CultureIn Source = value }; - viewSource.SortDescriptions.Add(new SortDescription("Descriptor.Type", ListSortDirection.Ascending)); - viewSource.SortDescriptions.Add(new SortDescription("Descriptor.Name", ListSortDirection.Ascending)); - viewSource.SortDescriptions.Add(new SortDescription("Descriptor.Description", ListSortDirection.Ascending)); - viewSource.GroupDescriptions.Add(new PropertyGroupDescription("Descriptor.Type")); + viewSource.SortDescriptions.Add(new SortDescription($"{nameof(Descriptor)}.{nameof(Descriptor.Type)}", ListSortDirection.Ascending)); + viewSource.SortDescriptions.Add(new SortDescription($"{nameof(Descriptor)}.{nameof(Descriptor.Name)}", ListSortDirection.Ascending)); + viewSource.SortDescriptions.Add(new SortDescription($"{nameof(Descriptor)}.{nameof(Descriptor.Description)}", ListSortDirection.Ascending)); + viewSource.GroupDescriptions.Add(new PropertyGroupDescription($"{nameof(Descriptor)}.{nameof(Descriptor.Type)}")); return viewSource.View.Groups; } diff --git a/RevitLookup/Views/Converters/ValueConverters.cs b/RevitLookup/Views/Converters/ValueConverters.cs index fbf4d1901..ca92fa97d 100644 --- a/RevitLookup/Views/Converters/ValueConverters.cs +++ b/RevitLookup/Views/Converters/ValueConverters.cs @@ -22,8 +22,6 @@ using System.Windows; using System.Windows.Data; using System.Windows.Markup; -using RevitLookup.Core.ComponentModel.Descriptors; -using RevitLookup.Core.Contracts; using RevitLookup.Core.Objects; namespace RevitLookup.Views.Converters; @@ -60,98 +58,6 @@ public object ConvertBack(object value, Type targetType, object parameter, Cultu throw new NotSupportedException(); } - public override object ProvideValue(IServiceProvider serviceProvider) - { - return this; - } -} - -public sealed class HandledDescriptorConverter : MarkupExtension, IValueConverter -{ - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - var descriptor = (Descriptor) value!; - if (descriptor is IDescriptorEnumerator enumerator) return !enumerator.IsEmpty; - return descriptor is IDescriptorCollector; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotSupportedException(); - } - - public override object ProvideValue(IServiceProvider serviceProvider) - { - return this; - } -} - -public sealed class ExceptionDescriptorConverter : MarkupExtension, IValueConverter -{ - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - var descriptor = (Descriptor) value!; - return descriptor is ExceptionDescriptor; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotSupportedException(); - } - - public override object ProvideValue(IServiceProvider serviceProvider) - { - return this; - } -} - -public sealed class SingleDescriptorConverter : DescriptorConverter -{ - public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - return ConvertInvalidNames(CreateSingleName((Descriptor) value!)); - } -} - -public sealed class CombinedDescriptorConverter : DescriptorConverter -{ - public override object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - return ConvertInvalidNames(CreateCombinedName((Descriptor) value!)); - } -} - -public abstract class DescriptorConverter : MarkupExtension, IValueConverter -{ - public abstract object Convert(object value, Type targetType, object parameter, CultureInfo culture); - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotSupportedException(); - } - - public static string CreateCombinedName(Descriptor descriptor) - { - if (string.IsNullOrEmpty(descriptor.Name)) return descriptor.Name; - return string.IsNullOrEmpty(descriptor.Description) ? descriptor.Name : $"{descriptor.Description}: {descriptor.Name}"; - } - - public static string CreateSingleName(Descriptor descriptor) - { - if (string.IsNullOrEmpty(descriptor.Name)) return descriptor.Name; - return string.IsNullOrEmpty(descriptor.Description) ? descriptor.Name : descriptor.Description; - } - - public string ConvertInvalidNames(string text) - { - return text switch - { - null => "", - "" => "", - _ => text - }; - } - public override object ProvideValue(IServiceProvider serviceProvider) { return this; diff --git a/RevitLookup/Views/Pages/DashboardView.xaml b/RevitLookup/Views/Pages/DashboardView.xaml index e8a2d3fe0..2008265ce 100644 --- a/RevitLookup/Views/Pages/DashboardView.xaml +++ b/RevitLookup/Views/Pages/DashboardView.xaml @@ -18,8 +18,10 @@ - - + \ No newline at end of file diff --git a/RevitLookup/Views/Pages/EventsView.xaml b/RevitLookup/Views/Pages/EventsView.xaml index 17f6fa77c..bbf04cbb1 100644 --- a/RevitLookup/Views/Pages/EventsView.xaml +++ b/RevitLookup/Views/Pages/EventsView.xaml @@ -6,9 +6,9 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:rl="http://revitlookup.com/xaml" xmlns:pages="clr-namespace:RevitLookup.Views.Pages" - xmlns:converters="clr-namespace:RevitLookup.Views.Converters" xmlns:markup="clr-namespace:RevitLookup.Views.Markup" xmlns:objects="clr-namespace:RevitLookup.Core.Objects" + xmlns:converters="clr-namespace:RevitLookup.Views.Converters" mc:Ignorable="d" d:DesignHeight="500" d:DesignWidth="500" @@ -96,7 +96,8 @@ + Converter={converters:SingleDescriptorConverter}, + Mode=OneTime}" /> @@ -117,19 +118,38 @@ CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" + CanUserSortColumns="False" CanUserReorderColumns="False" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled" - ItemsSource="{Binding ViewModel.FilteredSnoopableData}" - ScrollViewer.ScrollChanged="OnDataGridScrollChanged"> + ItemsSource="{Binding ViewModel.FilteredSnoopableData}"> - + Header="Member"> + + + + + + + + + @@ -151,7 +171,9 @@ Value="0" /> @@ -168,7 +190,9 @@ Value="Hand" /> + Text="{Binding Name, Mode=OneTime}" /> diff --git a/RevitLookup/Views/Pages/EventsView.xaml.cs b/RevitLookup/Views/Pages/EventsView.xaml.cs index f6e3e9d94..6f6e6d7f7 100644 --- a/RevitLookup/Views/Pages/EventsView.xaml.cs +++ b/RevitLookup/Views/Pages/EventsView.xaml.cs @@ -18,9 +18,7 @@ // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. -using System.Windows.Data; using System.Windows.Input; -using RevitLookup.Core.Objects; using RevitLookup.Services.Contracts; using RevitLookup.ViewModels.Pages; using Wpf.Ui.Appearance; @@ -40,10 +38,6 @@ public EventsView(IServiceProvider serviceProvider, ISettingsService settingsSer Theme.Apply(this, settingsService.Theme, settingsService.Background); - //Clear shapingStorage for remove duplications. WpfBug? - DataGrid.Items.GroupDescriptions!.Clear(); - DataGrid.Items.GroupDescriptions!.Add(new PropertyGroupDescription(nameof(Descriptor.Type))); - ViewModel.SearchResultsChanged += OnSearchResultsChanged; TreeView.SelectedItemChanged += OnTreeSelectionChanged; } diff --git a/RevitLookup/Views/Pages/SettingsView.xaml b/RevitLookup/Views/Pages/SettingsView.xaml index 276dcbfd3..b1faa8df4 100644 --- a/RevitLookup/Views/Pages/SettingsView.xaml +++ b/RevitLookup/Views/Pages/SettingsView.xaml @@ -9,7 +9,7 @@ xmlns:pages="clr-namespace:RevitLookup.Views.Pages" xmlns:markup="clr-namespace:RevitLookup.Views.Markup" mc:Ignorable="d" - d:DesignHeight="800" + d:DesignHeight="900" d:DesignWidth="500" d:DataContext="{d:DesignInstance pages:SettingsView}"> @@ -22,6 +22,8 @@ + IsChecked="{Binding ViewModel.IsModifyTabAllowed}" /> + + + - - - + IsChecked="{Binding ViewModel.IsPrivateAllowed}" /> + + + + + + + + + + + + diff --git a/RevitLookup/Views/Pages/SnoopView.xaml b/RevitLookup/Views/Pages/SnoopView.xaml index d76c72852..058ef889e 100644 --- a/RevitLookup/Views/Pages/SnoopView.xaml +++ b/RevitLookup/Views/Pages/SnoopView.xaml @@ -6,9 +6,9 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:rl="http://revitlookup.com/xaml" xmlns:pages="clr-namespace:RevitLookup.Views.Pages" - xmlns:converters="clr-namespace:RevitLookup.Views.Converters" xmlns:markup="clr-namespace:RevitLookup.Views.Markup" xmlns:objects="clr-namespace:RevitLookup.Core.Objects" + xmlns:converters="clr-namespace:RevitLookup.Views.Converters" mc:Ignorable="d" d:DesignHeight="500" d:DesignWidth="500" @@ -95,15 +95,16 @@ Converter={converters:TreeViewGroupConverter}}"> + ItemsSource="{Binding Items, Mode=OneTime}"> + Text="{Binding Name, Mode=OneTime}" /> + Converter={converters:SingleDescriptorConverter}, + Mode=OneTime}" /> @@ -126,19 +127,38 @@ CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" + CanUserSortColumns="False" CanUserReorderColumns="False" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled" - ItemsSource="{Binding ViewModel.FilteredSnoopableData}" - ScrollViewer.ScrollChanged="OnDataGridScrollChanged"> + ItemsSource="{Binding ViewModel.FilteredSnoopableData}"> - + Header="Member"> + + + + + + + + + @@ -182,7 +202,9 @@ Value="0" /> @@ -199,7 +221,9 @@ Value="Hand" /> + Text="{Binding Name, Mode=OneTime}" /> diff --git a/RevitLookup/Views/Pages/SnoopView.xaml.cs b/RevitLookup/Views/Pages/SnoopView.xaml.cs index a9a37ba43..653eb165c 100644 --- a/RevitLookup/Views/Pages/SnoopView.xaml.cs +++ b/RevitLookup/Views/Pages/SnoopView.xaml.cs @@ -18,9 +18,7 @@ // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. -using System.Windows.Data; using System.Windows.Input; -using RevitLookup.Core.Objects; using RevitLookup.Services.Contracts; using RevitLookup.ViewModels.Contracts; using Wpf.Ui.Appearance; @@ -35,15 +33,12 @@ public SnoopView(IServiceProvider serviceProvider, ISettingsService settingsServ ViewModel = (ISnoopViewModel) serviceProvider.GetService(typeof(ISnoopService)); DataContext = this; InitializeComponent(); - TreeViewControl = TreeView; + DataGridControl = DataGrid; + TreeViewControl = TreeView; Theme.Apply(this, settingsService.Theme, settingsService.Background); - //Clear shapingStorage for remove duplications. WpfBug? - DataGrid.Items.GroupDescriptions!.Clear(); - DataGrid.Items.GroupDescriptions!.Add(new PropertyGroupDescription(nameof(Descriptor.Type))); - Loaded += OnTreeSourceChanged; ViewModel.SearchResultsChanged += OnSearchResultsChanged; TreeView.SelectedItemChanged += OnTreeSelectionChanged; diff --git a/RevitLookup/Views/Pages/SnoopViewBase.xaml.cs b/RevitLookup/Views/Pages/SnoopViewBase.xaml.cs index a4052f787..1d5657080 100644 --- a/RevitLookup/Views/Pages/SnoopViewBase.xaml.cs +++ b/RevitLookup/Views/Pages/SnoopViewBase.xaml.cs @@ -18,9 +18,11 @@ // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. +using System.ComponentModel; using System.Text; using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Input; using CommunityToolkit.Mvvm.Input; @@ -32,16 +34,17 @@ using RevitLookup.Views.Extensions; using RevitLookup.Views.Utils; using Wpf.Ui.Controls.Navigation; -using static System.Windows.Controls.Primitives.GeneratorStatus; +using DataGrid = Wpf.Ui.Controls.DataGrid; using MenuItem = RevitLookup.Core.Objects.MenuItem; +using TreeView = Wpf.Ui.Controls.TreeView; namespace RevitLookup.Views.Pages; public class SnoopViewBase : Page, INavigableView { private readonly ISettingsService _settingsService; + private readonly DataGrid _dataGridControl; private bool _isUpdatingResults; - private int _scrollTick; protected SnoopViewBase(ISettingsService settingsService) { @@ -50,9 +53,34 @@ protected SnoopViewBase(ISettingsService settingsService) } protected TreeView TreeViewControl { get; init; } - protected DataGrid DataGridControl { get; init; } + + protected DataGrid DataGridControl + { + get => _dataGridControl; + init + { + _dataGridControl = value; + OnDataGridChanged(value); + } + } + public ISnoopViewModel ViewModel { get; init; } + private static void OnDataGridChanged(DataGrid control) + { + control.ItemsSourceChanged += (sender, _) => + { + var dataGrid = (DataGrid) sender; + + //Clear shapingStorage for remove duplications. WpfBug? + dataGrid.Items.GroupDescriptions!.Clear(); + dataGrid.Items.SortDescriptions.Add(new SortDescription(nameof(Descriptor.Depth), ListSortDirection.Descending)); + dataGrid.Items.SortDescriptions.Add(new SortDescription(nameof(Descriptor.MemberAttributes), ListSortDirection.Ascending)); + dataGrid.Items.SortDescriptions.Add(new SortDescription(nameof(Descriptor.Name), ListSortDirection.Ascending)); + dataGrid.Items.GroupDescriptions.Add(new PropertyGroupDescription(nameof(Descriptor.Type))); + }; + } + /// /// Expand treeView /// @@ -106,7 +134,7 @@ protected void OnSearchResultsChanged(object sender, EventArgs _) void OnItemContainerGeneratorOnStatusChanged(object statusSender, EventArgs __) { var generator = (ItemContainerGenerator) statusSender; - if (generator.Status != ContainersGenerated) return; + if (generator.Status != GeneratorStatus.ContainersGenerated) return; generator.StatusChanged -= OnItemContainerGeneratorOnStatusChanged; @@ -140,24 +168,6 @@ protected void OnGridMouseLeftButtonUp(object sender, RoutedEventArgs routedEven ViewModel.Navigate((Descriptor) DataGridControl.SelectedItem); } - /// - /// Disable tooltips while scrolling - /// - protected void OnDataGridScrollChanged(object sender, ScrollChangedEventArgs e) - { - if (e.VerticalChange != 0) _scrollTick = Environment.TickCount; - } - - /// - /// Disable tooltips while scrolling - /// - private void OnGridToolTipOpening(object o, ToolTipEventArgs args) - { - //Fixed by the tooltip work in 6.0-preview7 https://github.com/dotnet/wpf/pull/6058 but we use net48 - - if (_scrollTick != 0 && Environment.TickCount - _scrollTick < 73) args.Handled = true; - } - /// /// Create tooltip, menu /// @@ -197,32 +207,21 @@ private void CreateTreeTooltip(Descriptor descriptor, FrameworkElement row) .Append(descriptor.Name) .ToString() }; - - row.ToolTipOpening += OnGridToolTipOpening; } private void CreateGridTooltip(Descriptor descriptor, FrameworkElement row) { var builder = new StringBuilder(); - if ((descriptor.MemberAttributes & MemberAttributes.Private) != 0) - { - builder.Append("Private "); - } + if ((descriptor.MemberAttributes & MemberAttributes.Private) != 0) builder.Append("Private "); + if ((descriptor.MemberAttributes & MemberAttributes.Static) != 0) builder.Append("Static "); + if ((descriptor.MemberAttributes & MemberAttributes.Property) != 0) builder.Append("Property: "); + if ((descriptor.MemberAttributes & MemberAttributes.Extension) != 0) builder.Append("Extension: "); + if ((descriptor.MemberAttributes & MemberAttributes.Method) != 0) builder.Append("Method: "); + if ((descriptor.MemberAttributes & MemberAttributes.Event) != 0) builder.Append("Event: "); + if ((descriptor.MemberAttributes & MemberAttributes.Field) != 0) builder.Append("Field: "); - if ((descriptor.MemberAttributes & MemberAttributes.Static) != 0) - { - builder.Append("Static "); - } - - builder.Append(descriptor.MemberType switch - { - MemberType.Property => "Property: ", - MemberType.Extension => "Extension: ", - MemberType.Method => "Method: ", - _ => throw new ArgumentOutOfRangeException() - }) - .AppendLine(descriptor.Name) + builder.AppendLine(descriptor.Name) .Append("Type: ") .AppendLine(descriptor.Value.Descriptor.Type) .Append("Value: ") @@ -237,8 +236,6 @@ private void CreateGridTooltip(Descriptor descriptor, FrameworkElement row) { Content = builder.ToString() }; - - row.ToolTipOpening += OnGridToolTipOpening; } private void CreateTreeContextMenu(Descriptor descriptor, FrameworkElement row)