diff --git a/CUE4Parse b/CUE4Parse index 682f45f7..62a11913 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 682f45f762d049814a39e8fdfd8d1ee6bf1b1973 +Subproject commit 62a11913e10409e540b34e0286a734f98d6af3c7 diff --git a/FModel/MainWindow.xaml.cs b/FModel/MainWindow.xaml.cs index 6da880e6..3968bb69 100644 --- a/FModel/MainWindow.xaml.cs +++ b/FModel/MainWindow.xaml.cs @@ -240,7 +240,7 @@ namespace FModel private void OnMouseDoubleClick(object sender, MouseButtonEventArgs e) { - if (sender is not ListBox listBox) return; + if (!_applicationView.IsReady || sender is not ListBox listBox) return; UserSettings.Default.LoadingMode = ELoadingMode.Multiple; _applicationView.LoadingModes.LoadCommand.Execute(listBox.SelectedItems); } diff --git a/FModel/Views/Resources/Controls/Aed/BraceFoldingStrategy.cs b/FModel/Views/Resources/Controls/Aed/BraceFoldingStrategy.cs new file mode 100644 index 00000000..033970db --- /dev/null +++ b/FModel/Views/Resources/Controls/Aed/BraceFoldingStrategy.cs @@ -0,0 +1,139 @@ +using System.Collections.Generic; +using ICSharpCode.AvalonEdit; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.AvalonEdit.Folding; + +namespace FModel.Views.Resources.Controls +{ + /// + /// https://github.com/JTranOrg/JTranEdit/blob/master/JTranEdit/Classes/BraceFoldingStrategy.cs + /// + public interface IFoldingStrategy + { + IEnumerable UpdateFoldings(TextDocument document); + void CollapseAll(); + void ExpandAll(); + } + + public class JsonFoldingStrategies : IFoldingStrategy + { + private readonly List _strategies = new(); + private readonly FoldingManager _foldingManager; + private readonly IComparer _comparer = new FoldingComparer(); + + public JsonFoldingStrategies(TextEditor avalonEditor) + { + _foldingManager = FoldingManager.Install(avalonEditor.TextArea); + _strategies.Add(new BraceFoldingStrategy(avalonEditor, '{', '}')); + _strategies.Add(new BraceFoldingStrategy(avalonEditor, '[', ']')); + } + + public IEnumerable UpdateFoldings(TextDocument document) + { + var foldings = new List(); + foreach (var strategy in _strategies) + { + foldings.AddRange(strategy.UpdateFoldings(document)); + } + + foldings.Sort(_comparer); + _foldingManager.UpdateFoldings(foldings, -1); + + return foldings; + } + + public void CollapseAll() + { + if (_foldingManager.AllFoldings == null) + return; + + foreach (var folding in _foldingManager.AllFoldings) + { + folding.IsFolded = true; + } + + // Unfold the first fold (if any) to give a useful overview on content + var foldSection = _foldingManager.GetNextFolding(0); + if (foldSection != null) + foldSection.IsFolded = false; + } + + public void ExpandAll() + { + if (_foldingManager.AllFoldings == null) + return; + + foreach (var folding in _foldingManager.AllFoldings) + { + folding.IsFolded = false; + } + } + + private class FoldingComparer : IComparer + { + public int Compare(NewFolding x, NewFolding y) + { + return x.StartOffset.CompareTo(y.StartOffset); + } + } + } + + public class BraceFoldingStrategy : IFoldingStrategy + { + private readonly char _opening; + private readonly char _closing; + + public BraceFoldingStrategy(TextEditor editor, char o, char c) + { + _opening = o; + _closing = c; + UpdateFoldings(editor.Document); + } + + public IEnumerable UpdateFoldings(TextDocument document) + { + return CreateNewFoldings(document); + } + + public IEnumerable CreateNewFoldings(ITextSource document) + { + var newFoldings = new List(); + var startOffsets = new Stack(); + var lastNewLineOffset = 0; + + for (var i = 0; i < document.TextLength; i++) + { + var c = document.GetCharAt(i); + if (c == _opening) + { + startOffsets.Push(i); + } + else if (c == _closing && startOffsets.Count > 0) + { + var startOffset = startOffsets.Pop(); + if (startOffset < lastNewLineOffset) + { + newFoldings.Add(new NewFolding(startOffset, i + 1)); + } + } + else if (c is '\n' or '\r') + { + lastNewLineOffset = i + 1; + } + } + + newFoldings.Sort((a, b) => a.StartOffset.CompareTo(b.StartOffset)); + return newFoldings; + } + + public void CollapseAll() + { + throw new System.NotImplementedException(); + } + + public void ExpandAll() + { + throw new System.NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs b/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs index f85f4b31..73e5fe1a 100644 --- a/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs +++ b/FModel/Views/Resources/Controls/AvalonEditor.xaml.cs @@ -20,15 +20,15 @@ namespace FModel.Views.Resources.Controls private readonly Regex _hexColorRegex = new("\"Hex\": \"(?'target'[0-9A-Fa-f]{3,8})\"$", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); private readonly System.Windows.Controls.ToolTip _toolTip = new(); + private JsonFoldingStrategies _manager; public AvalonEditor() { CommandBindings.Add(new CommandBinding(NavigationCommands.Search, (_, e) => FindNext(e.Parameter != null))); - InitializeComponent(); + YesWeEditor = MyAvalonEditor; YesWeSearch = WpfSuckMyDick; - MyAvalonEditor.TextArea.TextView.ElementGenerators.Add(new GamePathElementGenerator()); MyAvalonEditor.TextArea.TextView.ElementGenerators.Add(new HexColorElementGenerator()); } @@ -83,6 +83,8 @@ namespace FModel.Views.Resources.Controls avalonEditor.Document == null || string.IsNullOrEmpty(avalonEditor.Document.Text)) return; + _manager ??= new JsonFoldingStrategies(avalonEditor); + _manager.UpdateFoldings(tabItem.Document); avalonEditor.Document.FileName = tabItem.Directory + '/' + tabItem.Header.SubstringBeforeLast('.'); if (!tabItem.ShouldScroll) return; diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml index 387a134c..783022e1 100644 --- a/FModel/Views/Resources/Resources.xaml +++ b/FModel/Views/Resources/Resources.xaml @@ -7,6 +7,7 @@ xmlns:audioControls="clr-namespace:FModel.Views.Resources.Controls.Aup" xmlns:converters="clr-namespace:FModel.Views.Resources.Converters" xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit" + xmlns:folding="clr-namespace:ICSharpCode.AvalonEdit.Folding;assembly=ICSharpCode.AvalonEdit" xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI" xmlns:adonisConverters="clr-namespace:AdonisUI.Converters;assembly=AdonisUI" xmlns:adonisExtensions="clr-namespace:AdonisUI.Extensions;assembly=AdonisUI" @@ -1635,4 +1636,11 @@ + + \ No newline at end of file