Skip to content

Commit

Permalink
Improved UI a bit and removed array values from search results (due t…
Browse files Browse the repository at this point in the history
…o extreme lag)
  • Loading branch information
AngryCarrot789 committed May 3, 2023
1 parent 3455f74 commit 8b4b395
Show file tree
Hide file tree
Showing 43 changed files with 840 additions and 593 deletions.
194 changes: 146 additions & 48 deletions .idea/.idea.MCNBTEditor/.idea/workspace.xml

Large diffs are not rendered by default.

21 changes: 15 additions & 6 deletions MCNBTEditor.Core/Actions/Contexts/DataContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,30 @@ public void Set(string key, object value) {
}

public void Merge(IDataContext ctx) {
foreach (object o in ctx.Context) {
this.ContextList.Add(o);
// ToList() makes this function faster... as long as ctx.Context has more than a few elements
// this.ContextList.AddRange(ctx.Context.Where(x => this.ContextList.IndexOf(x) == -1).ToList());
foreach (object value in ctx.Context) {
if (this.ContextList.IndexOf(value) == -1) {
this.ContextList.Add(value);
}
}

if (ctx is DataContext ctxImpl) { // slight optimisation; no need to deconstruct KeyValuePairs into tuples
if (ctxImpl.EntryMap != null && ctxImpl.EntryMap.Count > 0) {
Dictionary<string, object> map = this.EntryMap ?? (this.EntryMap = new Dictionary<string, object>());
foreach (KeyValuePair<string, object> entry in ctxImpl.EntryMap) {
map[entry.Key] = entry.Value;
if (this.EntryMap == null) {
this.EntryMap = new Dictionary<string, object>(ctxImpl.EntryMap);
}
else {
Dictionary<string, object> map = this.EntryMap = new Dictionary<string, object>();
foreach (KeyValuePair<string, object> entry in ctxImpl.EntryMap) {
map[entry.Key] = entry.Value;
}
}
}
}
else {
List<(string, object)> list = ctx.CustomData.ToList();
if (list.Count <= 0) {
if (list.Count < 1) {
return;
}

Expand Down
6 changes: 5 additions & 1 deletion MCNBTEditor.Core/BaseRelayCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ public virtual bool CanExecute(object parameter) {
/// </para>
/// </summary>
public virtual void RaiseCanExecuteChanged() {
this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
if (this.CanExecuteChanged != null) {
IoC.Dispatcher.Invoke(() => {
this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
});
}
}

/// <summary>
Expand Down
53 changes: 33 additions & 20 deletions MCNBTEditor.Core/BaseViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ protected BaseViewModel() {

}

private static Dictionary<object, object> GetMap(BaseViewModel vm) {
return vm.internalData ?? (vm.internalData = new Dictionary<object, object>());
}

public static T GetInternalData<T>(BaseViewModel viewModel, object key) {
return GetInternalData(viewModel, key) is T t ? t : default;
}
Expand All @@ -29,67 +33,76 @@ public static object GetInternalData(BaseViewModel viewModel, object key) {
return map == null ? null : map.TryGetValue(key, out object data) ? data : null;
}

public static bool TryGetInternalData<T>(BaseViewModel viewModel, object key, out T value) {
Dictionary<object, object> map = (viewModel ?? throw new ArgumentNullException(nameof(viewModel))).internalData;
if (map != null && map.TryGetValue(key, out object data) && data is T t) {
value = t;
return true;
}

value = default;
return false;
}

public static void SetInternalData(BaseViewModel viewModel, object key, object value) {
if (viewModel == null) {
if (viewModel == null)
throw new ArgumentNullException(nameof(viewModel));
}
if (key == null)
throw new ArgumentNullException(nameof(key));
GetMap(viewModel)[key] = value;
}

(viewModel.internalData ?? (viewModel.internalData = new Dictionary<object, object>()))[key] = value;
public static bool ClearInternalData(BaseViewModel viewModel, object key) {
if (viewModel == null)
throw new ArgumentNullException(nameof(viewModel));
if (key == null)
throw new ArgumentNullException(nameof(key));
Dictionary<object, object> map = viewModel.internalData;
return map != null && map.Remove(key);
}

public void RaisePropertyChanged([CallerMemberName] string propertyName = null) {
if (propertyName == null) {
if (propertyName == null)
throw new ArgumentNullException(nameof(propertyName), "Property Name is null");
}

this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public void RaisePropertyChanged<T>(ref T property, T newValue, [CallerMemberName] string propertyName = null) {
if (propertyName == null) {
if (propertyName == null)
throw new ArgumentNullException(nameof(propertyName), "Property Name is null");
}

property = newValue;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public void RaisePropertyChanged<T>(ref T property, T newValue, Action postCallback, [CallerMemberName] string propertyName = null) {
if (propertyName == null) {
if (propertyName == null)
throw new ArgumentNullException(nameof(propertyName), "Property Name is null");
}

property = newValue;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
postCallback?.Invoke();
}

public void RaisePropertyChanged<T>(ref T property, T newValue, Action<T> postCallback, [CallerMemberName] string propertyName = null) {
if (propertyName == null) {
if (propertyName == null)
throw new ArgumentNullException(nameof(propertyName), "Property Name is null");
}

property = newValue;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
postCallback?.Invoke(property);
}

public void RaisePropertyChanged<T>(ref T property, T newValue, Action<T> preCallback, Action<T> postCallback, [CallerMemberName] string propertyName = null) {
if (propertyName == null) {
if (propertyName == null)
throw new ArgumentNullException(nameof(propertyName), "Property Name is null");
}

preCallback?.Invoke(property);
property = newValue;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
postCallback?.Invoke(property);
}

public void RaisePropertyChangedIfChanged<T>(ref T property, T newValue, [CallerMemberName] string propertyName = null) {
if (propertyName == null) {
if (propertyName == null)
throw new ArgumentNullException(nameof(propertyName), "Property Name is null");
}

if (EqualityComparer<T>.Default.Equals(property, newValue)) {
return;
}
Expand Down
42 changes: 41 additions & 1 deletion MCNBTEditor.Core/Explorer/Dialog/TagPrimitiveEditorViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,24 @@ public string Name {
private string value;
public string Value {
get => this.value;
set => this.RaisePropertyChanged(ref this.value, value);
set {
if (this.value == value) {
return;
}

this.RaisePropertyChanged(ref this.value, value);
if (!this.IsBoolButtonVisible && this.TagType == NBTType.Byte) {
this.IsBoolButtonVisible = true;
}

if (this.IsBoolButtonVisible) {
switch (value) {
case "0": this.IsBooleanChecked = false; break;
case "1": this.IsBooleanChecked = true; break;
default: this.IsBooleanChecked = null; break;
}
}
}
}

private bool canEditName;
Expand All @@ -41,6 +58,28 @@ public bool CanEditValue {
set => this.RaisePropertyChanged(ref this.canEditValue, value);
}

private bool? isBooleanChecked;
public bool? IsBooleanChecked {
get => this.isBooleanChecked;
set {
if (this.isBooleanChecked != value) {
switch (value) {
case true: this.Value = "1"; break;
case false: this.Value = "0"; break;
case null: this.Value = "2"; break;
}

this.RaisePropertyChanged(ref this.isBooleanChecked, value);
}
}
}

private bool isBoolButtonVisible;
public bool IsBoolButtonVisible {
get => this.isBoolButtonVisible;
set => this.RaisePropertyChanged(ref this.isBoolButtonVisible, value);
}

private NBTType tagType;
public NBTType TagType {
get => this.tagType;
Expand All @@ -54,6 +93,7 @@ public NBTType TagType {
throw new ArgumentOutOfRangeException(nameof(value), value, "Type is not primitive: " + value);
}

this.IsBoolButtonVisible = this.tagType == NBTType.Byte;
this.RaisePropertyChanged(ref this.tagType, value);
}
}
Expand Down
28 changes: 7 additions & 21 deletions MCNBTEditor.Core/Explorer/IExtendedTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,18 @@

namespace MCNBTEditor.Core.Explorer {
public interface IExtendedTree {
BaseTreeItemViewModel GetSelectedItem();

bool IsItemExpanded(BaseTreeItemViewModel item);

void SetExpanded(BaseTreeItemViewModel nbt);

bool IsExpanded(BaseTreeItemViewModel nbt);

/// <summary>
/// Expands the given collection of items (in which the first item is the root item) all the way down to the last item
/// <para>
/// The repeat functionality will repeat it N number of items due to WPF item container generation issues
/// </para>
/// <para>
/// This is a fairly expensive operation!
/// </para>
/// Whether an async navigation is currently being processed
/// </summary>
/// <param name="items"></param>
/// <returns></returns>
Task<bool> RepeatExpandHierarchyFromRootAsync(IEnumerable<BaseTreeItemViewModel> items);
bool IsNavigating { get; }

BaseTreeItemViewModel GetSelectedItem();

Task ExpandItemSubTree(BaseTreeItemViewModel item);
bool? IsItemExpanded(BaseTreeItemViewModel item);

bool ExpandHierarchyFromRoot(IEnumerable<BaseTreeItemViewModel> items, bool select = true);
Task<bool> NavigateAsync(IEnumerable<BaseTreeItemViewModel> items);

Task<bool> MainExpandHierarchy(IEnumerable<int> items);
Task<bool> NavigateToItemAsync(BaseTreeItemViewModel item);

event SelectionChangedEventHandler<BaseTreeItemViewModel> SelectionChanged;
}
Expand Down
8 changes: 6 additions & 2 deletions MCNBTEditor.Core/Explorer/NBT/BaseTagViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,13 @@ public virtual void GetContext(List<IContextEntry> list) {
}

list.Add(new CommandContextEntry("Copy (Binary)", this.CopyBinaryToClipboardCommand));
// list.Add(SeparatorEntry.Instance);
if (this is TagDataFileViewModel datFileAgain) {
list.Add(SeparatorEntry.Instance);
if (this is BaseTagCollectionViewModel tagCollectionAgain) {
list.Add(new ActionContextEntry(tagCollectionAgain, "actions.nbt.find"));
list.Add(SeparatorEntry.Instance);
}

if (this is TagDataFileViewModel datFileAgain) {
list.Add(new ShortcutCommandContextEntry("Application/EditorView/NBTTag/RemoveFromParent", this.RemoveFromParentCommand));
list.Add(new CommandContextEntry("Delete FILE", datFileAgain.DeleteFileCommand));
}
Expand Down
16 changes: 8 additions & 8 deletions MCNBTEditor/AdvancedContextService/ContextStyles.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

</Style>

<!-- d:DataContext="{d:DesignInstance t:CommandContextEntry}" | Dammit visual studio why won't you accept d:DataContext on styles :'( -->
<Style x:Key="ContextualEntryCommandMenuItemStyle" TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
<!-- Dammit visual studio why won't you accept d:DataContext on styles :'( -->
<Style d:DataContext="{d:DesignInstance t:CommandContextEntry}" x:Key="ContextualEntryCommandMenuItemStyle" TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
<Setter Property="Header" Value="{Binding Header, Mode=OneWay}"/>
<Setter Property="InputGestureText" Value="{Binding InputGestureText, Mode=OneWay}"/>
<Setter Property="ToolTip" Value="{Binding ToolTip, Mode=OneWay}"/>
Expand All @@ -27,21 +27,21 @@
<Setter Property="CommandParameter" Value="{Binding CommandParameter}"/>
</Style>

<!-- d:DataContext="{d:DesignInstance t:ActionContextEntry}" | Dammit visual studio why won't you accept d:DataContext on styles :'( -->
<Style x:Key="ContextualEntryActionMenuItemStyle" TargetType="{x:Type acs:AdvancedActionMenuItem}" BasedOn="{StaticResource {x:Type acs:AdvancedActionMenuItem}}">
<!-- -->
<Style d:DataContext="{d:DesignInstance t:ActionContextEntry}" x:Key="ContextualEntryActionMenuItemStyle" TargetType="{x:Type acs:AdvancedActionMenuItem}" BasedOn="{StaticResource {x:Type acs:AdvancedActionMenuItem}}">
<Setter Property="ActionId" Value="{Binding ActionId, Mode=OneWay}"/>
<Setter Property="ItemsSource" Value="{Binding Children, Mode=OneTime}"/>
</Style>

<!-- d:DataContext="{d:DesignInstance t:GroupContextEntry}" | Dammit visual studio why won't you accept d:DataContext on styles :'( -->
<Style x:Key="ContextualEntryGroupMenuItemStyle" TargetType="{x:Type acs:AdvancedMenuItem}" BasedOn="{StaticResource {x:Type acs:AdvancedMenuItem}}">
<!-- -->
<Style d:DataContext="{d:DesignInstance t:GroupContextEntry}" x:Key="ContextualEntryGroupMenuItemStyle" TargetType="{x:Type acs:AdvancedMenuItem}" BasedOn="{StaticResource {x:Type acs:AdvancedMenuItem}}">
<Setter Property="Header" Value="{Binding Header, Mode=OneWay}"/>
<Setter Property="ToolTip" Value="{Binding ToolTip, Mode=OneWay}"/>
<Setter Property="ItemsSource" Value="{Binding Children, Mode=OneTime}"/>
</Style>

<!-- d:DataContext="{d:DesignInstance t:ShortcutCommandContextEntry}" | Dammit visual studio why won't you accept d:DataContext on styles :'( -->
<Style x:Key="ContextualEntryShortcutCommandMenuItemStyle" TargetType="{x:Type acs:AdvancedShortcutMenuItem}" BasedOn="{StaticResource {x:Type acs:AdvancedMenuItem}}">
<!-- -->
<Style d:DataContext="{d:DesignInstance t:ShortcutCommandContextEntry}" x:Key="ContextualEntryShortcutCommandMenuItemStyle" TargetType="{x:Type acs:AdvancedShortcutMenuItem}" BasedOn="{StaticResource {x:Type acs:AdvancedMenuItem}}">
<Setter Property="ShortcutIds" Value="{Binding ShortcutIds, Mode=OneTime}"/>
<Setter Property="Command" Value="{Binding Command, Mode=TwoWay}"/>
<Setter Property="CommandParameter" Value="{Binding CommandParameter, Mode=TwoWay}"/>
Expand Down
4 changes: 2 additions & 2 deletions MCNBTEditor/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:MCNBTEditor.Controls"
Startup="Application_Startup">
Startup="Application_Startup"
ShutdownMode="OnMainWindowClose">
<Application.Resources>
<ResourceDictionary>
<Style TargetType="{x:Type controls:ExtendedTreeView}" BasedOn="{StaticResource {x:Type TreeView}}"/>

<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/SoftDark.xaml"/>
<ResourceDictionary Source="Themes/ControlColoursSoftDarkBlue.xaml"/>
Expand Down
8 changes: 8 additions & 0 deletions MCNBTEditor/Controls/ControlStyles.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@

<Style TargetType="{x:Type Run}" x:Key="NBTTagValueRunStyle">
<Setter Property="Foreground" Value="{DynamicResource AREghZyBrush.Foreground.Deeper}"/>
<Setter Property="FontFamily" Value="Consolas"/>
</Style>

<!-- TODO: ??? not sure how to do this without using a style for each type of tag -->
<Style x:Key="TagTooltipStyle" TargetType="{x:Type ToolTip}" BasedOn="{StaticResource {x:Type ToolTip}}">
<Setter Property="Background" Value="{DynamicResource AREghZyBrush.Primary.2.Background.Static}"/>
</Style>

<inlines:NBTCollectionInlineHeaderConverter x:Key="NBTCollectionInlinesNameConverter" TagNameRunStyle="{StaticResource NBTTagNameRunStyle}" TagDataRunStyle="{StaticResource NBTTagValueRunStyle}"/>
Expand Down Expand Up @@ -267,4 +273,6 @@
<Setter Property="Background" Value="{DynamicResource AREghZyBrush.Deep.2.Background.Static}"/>
<Setter Property="BorderBrush" Value="{DynamicResource AREghZyBrush.Primary.2.Border.Static}"/>
</Style>

<Style TargetType="{x:Type controls:ExtendedTreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}"/>
</ResourceDictionary>
Loading

0 comments on commit 8b4b395

Please sign in to comment.