Skip to content

Commit

Permalink
Mouse new window support
Browse files Browse the repository at this point in the history
  • Loading branch information
Nice3point committed Dec 3, 2023
1 parent 2124a64 commit fa51d90
Show file tree
Hide file tree
Showing 19 changed files with 668 additions and 436 deletions.
8 changes: 7 additions & 1 deletion RevitLookup.UI.Demo/Services/MoqLookupService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,13 @@ public ILookupServiceDependsStage Snoop(SnoopableObject snoopableObject)
_serviceProvider.GetService<ISnoopVisualService>()!.Snoop(snoopableObject);
return this;
}


public ILookupServiceDependsStage Snoop(IReadOnlyCollection<SnoopableObject> snoopableObjects)
{
_serviceProvider.GetService<ISnoopVisualService>()!.Snoop(snoopableObjects);
return this;
}

public ILookupServiceShowStage DependsOn(IServiceProvider provider)
{
_owner = (Window) provider.GetService<IWindow>();
Expand Down
16 changes: 12 additions & 4 deletions RevitLookup.UI.Demo/Services/MoqSnoopVisualService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,21 @@ public void Snoop(SnoopableObject snoopableObject)
{
viewModel.SnoopableObjects = new[] {snoopableObject};
}

viewModel.SnoopableData = Array.Empty<Descriptor>();
}
catch (Exception exception)
{
notificationService.ShowError("Invalid object", exception);
}
}

public void Snoop(IReadOnlyCollection<SnoopableObject> snoopableObjects)
{
viewModel.SnoopableObjects = snoopableObjects;
viewModel.SnoopableData = Array.Empty<Descriptor>();
}

public async Task SnoopAsync(SnoopableType snoopableType)
{
switch (snoopableType)
Expand Down Expand Up @@ -89,8 +97,8 @@ public async Task SnoopAsync(SnoopableType snoopableType)
_ => throw new ArgumentOutOfRangeException(nameof(snoopableType), snoopableType, null)
};

viewModel.SnoopableObjects = await GenerateObjectsAsync(generationCount);
viewModel.SnoopableData = Array.Empty<Descriptor>();
var items = await GenerateObjectsAsync(generationCount);
Snoop(items);
UpdateWindowVisibility(Visibility.Visible);
}

Expand All @@ -108,10 +116,10 @@ private static async Task<IReadOnlyCollection<SnoopableObject>> GenerateObjectsA
return await Task.Run(() => new Faker<SnoopableObject>()
.CustomInstantiator(faker =>
{
if (faker.IndexFaker % 2000 == 0) return new SnoopableObject(null);
if (faker.IndexFaker % 2000 == 0) return new SnoopableObject((object) null);
if (faker.IndexFaker % 1000 == 0) return new SnoopableObject(string.Empty);
if (faker.IndexFaker % 700 == 0) return new SnoopableObject(faker.Make(150, () => faker.Internet.UserName()));
if (faker.IndexFaker % 500 == 0) return new SnoopableObject(typeof(Debug));
if (faker.IndexFaker % 500 == 0) return new SnoopableObject(typeof(DateTime));
if (faker.IndexFaker % 200 == 0) return new SnoopableObject(faker.Lorem.Sentence());
if (faker.IndexFaker % 100 == 0) return new SnoopableObject(new Color(faker.Random.Byte(), faker.Random.Byte(), faker.Random.Byte()));
if (faker.IndexFaker % 5 == 0) return new SnoopableObject(faker.Random.Int(0));
Expand Down
13 changes: 9 additions & 4 deletions RevitLookup.UI.Demo/ViewModels/MoqSnoopViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,18 @@ public sealed partial class MoqSnoopViewModel(NotificationService notificationSe

public SnoopableObject SelectedObject { get; set; }

public void Navigate(Descriptor selectedItem)
public void Navigate(SnoopableObject selectedItem)
{
if (selectedItem.Value.Descriptor is not IDescriptorCollector) return;
if (selectedItem.Value.Descriptor is IDescriptorEnumerator {IsEmpty: true}) return;
Host.GetService<ILookupService>()
.Snoop(selectedItem)
.DependsOn(provider)
.Show<SnoopView>();
}

public void Navigate(IReadOnlyCollection<SnoopableObject> selectedItems)
{
Host.GetService<ILookupService>()
.Snoop(selectedItem.Value)
.Snoop(selectedItems)
.DependsOn(provider)
.Show<SnoopView>();
}
Expand Down
1 change: 1 addition & 0 deletions RevitLookup/Services/Contracts/ILookupService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public interface ILookupService : ILookupServiceDependsStage, ILookupServiceShow
{
ILookupServiceDependsStage Snoop(SnoopableType snoopableType);
ILookupServiceDependsStage Snoop(SnoopableObject snoopableObject);
ILookupServiceDependsStage Snoop(IReadOnlyCollection<SnoopableObject> snoopableObjects);
new ILookupServiceShowStage DependsOn(IServiceProvider provider);
new ILookupServiceExecuteStage Show<T>() where T : Page;
}
Expand Down
1 change: 1 addition & 0 deletions RevitLookup/Services/Contracts/ISnoopVisualService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ namespace RevitLookup.Services.Contracts;
public interface ISnoopVisualService
{
void Snoop(SnoopableObject snoopableObject);
void Snoop(IReadOnlyCollection<SnoopableObject> snoopableObjects);
Task SnoopAsync(SnoopableType snoopableType);
}
6 changes: 6 additions & 0 deletions RevitLookup/Services/LookupService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ public ILookupServiceDependsStage Snoop(SnoopableObject snoopableObject)
return this;
}

public ILookupServiceDependsStage Snoop(IReadOnlyCollection<SnoopableObject> snoopableObjects)
{
_serviceProvider.GetService<ISnoopVisualService>()!.Snoop(snoopableObjects);
return this;
}

public ILookupServiceShowStage DependsOn(IServiceProvider provider)
{
_owner = (Window) provider.GetService<IWindow>();
Expand Down
17 changes: 12 additions & 5 deletions RevitLookup/Services/SnoopVisualService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,30 @@ public void Snoop(SnoopableObject snoopableObject)
{
try
{
IReadOnlyCollection<SnoopableObject> snoopableObjects;
if (snoopableObject.Descriptor is IDescriptorEnumerator {IsEmpty: false} descriptor)
{
viewModel.SnoopableObjects = descriptor.ParseEnumerable(snoopableObject);
snoopableObjects = descriptor.ParseEnumerable(snoopableObject);
}
else
{
viewModel.SnoopableObjects = new[] {snoopableObject};
snoopableObjects = new[] {snoopableObject};
}

viewModel.SnoopableData = Array.Empty<Descriptor>();
Snoop(snoopableObjects);
}
catch (Exception exception)
{
notificationService.ShowError("Invalid object", exception);
}
}

public void Snoop(IReadOnlyCollection<SnoopableObject> snoopableObjects)
{
viewModel.SnoopableObjects = snoopableObjects;
viewModel.SnoopableData = Array.Empty<Descriptor>();
}

public async Task SnoopAsync(SnoopableType snoopableType)
{
try
Expand All @@ -67,8 +74,8 @@ public async Task SnoopAsync(SnoopableType snoopableType)
break;
}

viewModel.SnoopableObjects = await Application.ExternalElementHandler.RaiseAsync(_ => Selector.Snoop(snoopableType));
viewModel.SnoopableData = Array.Empty<Descriptor>();
var snoopableObjects = await Application.ExternalElementHandler.RaiseAsync(_ => Selector.Snoop(snoopableType));
Snoop(snoopableObjects);
}
catch (OperationCanceledException)
{
Expand Down
3 changes: 2 additions & 1 deletion RevitLookup/ViewModels/Contracts/ISnoopViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ public interface ISnoopViewModel
IAsyncRelayCommand RefreshMembersCommand { get; }
public string SearchText { get; set; }
public SnoopableObject SelectedObject { get; set; }
void Navigate(Descriptor selectedItem);
void Navigate(SnoopableObject selectedItem);
void Navigate(IReadOnlyCollection<SnoopableObject> selectedItems);
}
13 changes: 9 additions & 4 deletions RevitLookup/ViewModels/Pages/SnoopViewModelBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,18 @@ public abstract partial class SnoopViewModelBase(NotificationService notificatio

public SnoopableObject SelectedObject { get; set; }

public void Navigate(Descriptor selectedItem)
public void Navigate(SnoopableObject selectedItem)
{
if (selectedItem.Value.Descriptor is not IDescriptorCollector) return;
if (selectedItem.Value.Descriptor is IDescriptorEnumerator {IsEmpty: true}) return;
Host.GetService<ILookupService>()
.Snoop(selectedItem)
.DependsOn(provider)
.Show<SnoopView>();
}

public void Navigate(IReadOnlyCollection<SnoopableObject> selectedItems)
{
Host.GetService<ILookupService>()
.Snoop(selectedItem.Value)
.Snoop(selectedItems)
.DependsOn(provider)
.Show<SnoopView>();
}
Expand Down
153 changes: 153 additions & 0 deletions RevitLookup/Views/Pages/Abstraction/SnoopViewBase.ContextMenu.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// 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.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using RevitLookup.Core.Contracts;
using RevitLookup.Core.Objects;
using RevitLookup.Views.Extensions;
using RevitLookup.Views.Utils;

namespace RevitLookup.Views.Pages.Abstraction;

public partial class SnoopViewBase
{
private void CreateTreeContextMenu(Descriptor descriptor, FrameworkElement row)
{
var contextMenu = new ContextMenu
{
Resources = Resources
};

contextMenu.AddMenuItem("CopyMenuItem")
.SetCommand(descriptor, parameter => Clipboard.SetText(parameter.Name))
.SetShortcut(row, ModifierKeys.Control, Key.C);
contextMenu.AddMenuItem("HelpMenuItem")
.SetCommand(descriptor, parameter => HelpUtils.ShowHelp(parameter.TypeFullName))
.SetShortcut(row, Key.F1);

if (descriptor is IDescriptorConnector connector) connector.RegisterMenu(contextMenu, row);
row.ContextMenu = contextMenu;
}

private void CreateGridContextMenu(DataGrid dataGrid)
{
var contextMenu = new ContextMenu
{
Resources = Resources
};

contextMenu.AddMenuItem("RefreshMenuItem")
.SetCommand(ViewModel.RefreshMembersCommand)
.SetGestureText(Key.F5);

contextMenu.AddSeparator();
contextMenu.AddLabel("Columns");

contextMenu.AddMenuItem("CheckableMenuItem")
.SetHeader("Time")
.SetCommand(dataGrid.Columns[2].Visibility == Visibility.Visible, parameter =>
{
dataGrid.Columns[2].Visibility = parameter ? Visibility.Collapsed : Visibility.Visible;
_settingsService.ShowTimeColumn = !parameter;
});

contextMenu.AddSeparator();
contextMenu.AddLabel("Show");

contextMenu.AddMenuItem("CheckableMenuItem")
.SetHeader("Events")
.SetCommand(_settingsService.IncludeEvents, parameter =>
{
_settingsService.IncludeEvents = !parameter;
return RefreshGridAsync();
});
contextMenu.AddMenuItem("CheckableMenuItem")
.SetHeader("Extensions")
.SetCommand(_settingsService.IncludeExtensions, parameter =>
{
_settingsService.IncludeExtensions = !parameter;
return RefreshGridAsync();
});
contextMenu.AddMenuItem("CheckableMenuItem")
.SetHeader("Fields")
.SetCommand(_settingsService.IncludeFields, parameter =>
{
_settingsService.IncludeFields = !parameter;
return RefreshGridAsync();
});
contextMenu.AddMenuItem("CheckableMenuItem")
.SetHeader("Non-public")
.SetCommand(_settingsService.IncludePrivate, parameter =>
{
_settingsService.IncludePrivate = !parameter;
return RefreshGridAsync();
});
contextMenu.AddMenuItem("CheckableMenuItem")
.SetHeader("Root hierarchy")
.SetCommand(_settingsService.IncludeRootHierarchy, parameter =>
{
_settingsService.IncludeRootHierarchy = !parameter;
return RefreshGridAsync();
});
contextMenu.AddMenuItem("CheckableMenuItem")
.SetHeader("Static")
.SetCommand(_settingsService.IncludeStatic, parameter =>
{
_settingsService.IncludeStatic = !parameter;
return RefreshGridAsync();
});
contextMenu.AddMenuItem("CheckableMenuItem")
.SetHeader("Unsupported")
.SetCommand(_settingsService.IncludeUnsupported, parameter =>
{
_settingsService.IncludeUnsupported = !parameter;
return RefreshGridAsync();
});

dataGrid.ContextMenu = contextMenu;
}

private void CreateGridRowContextMenu(Descriptor descriptor, FrameworkElement row)
{
var contextMenu = new ContextMenu
{
Resources = Resources
};

contextMenu.AddMenuItem("CopyMenuItem")
.SetCommand(descriptor, parameter => Clipboard.SetText($"{parameter.Name}: {parameter.Value.Descriptor.Name}"))
.SetShortcut(row, ModifierKeys.Control, Key.C);

contextMenu.AddMenuItem("CopyMenuItem")
.SetHeader("Copy value")
.SetCommand(descriptor, parameter => Clipboard.SetText(parameter.Value.Descriptor.Name))
.SetShortcut(row, ModifierKeys.Control | ModifierKeys.Shift, Key.C)
.SetAvailability(descriptor.Value.Descriptor.Name is not null);

contextMenu.AddMenuItem("HelpMenuItem")
.SetCommand(descriptor, parameter => HelpUtils.ShowHelp(parameter.TypeFullName, parameter.Name))
.SetShortcut(row, new KeyGesture(Key.F1));

if (descriptor.Value.Descriptor is IDescriptorConnector connector) connector.RegisterMenu(contextMenu, row);
row.ContextMenu = contextMenu;
}
}
40 changes: 40 additions & 0 deletions RevitLookup/Views/Pages/Abstraction/SnoopViewBase.Gestures.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.Windows.Input;
using CommunityToolkit.Mvvm.Input;

namespace RevitLookup.Views.Pages.Abstraction;

public partial class SnoopViewBase
{
private void AddShortcuts()
{
var command = new AsyncRelayCommand(() => ViewModel.RefreshMembersCommand.ExecuteAsync(null));
InputBindings.Add(new KeyBinding(command, new KeyGesture(Key.F5)));
}

private void OnPageKeyPressed(object sender, KeyEventArgs e)
{
if (SearchBoxControl.IsKeyboardFocused) return;
if (e.KeyboardDevice.Modifiers != ModifierKeys.None) return;
if (e.Key is >= Key.D0 and <= Key.Z or >= Key.NumPad0 and <= Key.NumPad9) SearchBoxControl.Focus();
}
}
Loading

0 comments on commit fa51d90

Please sign in to comment.