mirror of
https://github.com/4sval/FModel.git
synced 2026-06-21 15:30:05 -05:00
kinda useful folding shortcuts
This commit is contained in:
parent
ed5dfe0a0a
commit
721f543d99
|
|
@ -5,60 +5,23 @@ using ICSharpCode.AvalonEdit.Folding;
|
|||
|
||||
namespace FModel.Views.Resources.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// https://github.com/JTranOrg/JTranEdit/blob/master/JTranEdit/Classes/BraceFoldingStrategy.cs
|
||||
/// </summary>
|
||||
public interface IFoldingStrategy
|
||||
public class JsonFoldingStrategies
|
||||
{
|
||||
IEnumerable<NewFolding> UpdateFoldings(TextDocument document);
|
||||
void CollapseAll();
|
||||
void ExpandAll();
|
||||
}
|
||||
|
||||
public class JsonFoldingStrategies : IFoldingStrategy
|
||||
{
|
||||
private readonly List<IFoldingStrategy> _strategies = new();
|
||||
private readonly BraceFoldingStrategy _strategy;
|
||||
private readonly FoldingManager _foldingManager;
|
||||
private readonly IComparer<NewFolding> _comparer = new FoldingComparer();
|
||||
|
||||
public JsonFoldingStrategies(TextEditor avalonEditor)
|
||||
{
|
||||
_foldingManager = FoldingManager.Install(avalonEditor.TextArea);
|
||||
_strategies.Add(new BraceFoldingStrategy(avalonEditor, '{', '}'));
|
||||
_strategies.Add(new BraceFoldingStrategy(avalonEditor, '[', ']'));
|
||||
_strategy = new BraceFoldingStrategy(avalonEditor);
|
||||
}
|
||||
|
||||
public IEnumerable<NewFolding> UpdateFoldings(TextDocument document)
|
||||
public void UpdateFoldings(TextDocument document)
|
||||
{
|
||||
var foldings = new List<NewFolding>();
|
||||
foreach (var strategy in _strategies)
|
||||
{
|
||||
foldings.AddRange(strategy.UpdateFoldings(document));
|
||||
}
|
||||
|
||||
foldings.Sort(_comparer);
|
||||
_foldingManager.UpdateFoldings(foldings, -1);
|
||||
|
||||
return foldings;
|
||||
_foldingManager.UpdateFoldings(_strategy.UpdateFoldings(document), -1);
|
||||
}
|
||||
|
||||
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()
|
||||
public void UnfoldAll()
|
||||
{
|
||||
if (_foldingManager.AllFoldings == null)
|
||||
return;
|
||||
|
|
@ -68,72 +31,91 @@ namespace FModel.Views.Resources.Controls
|
|||
folding.IsFolded = false;
|
||||
}
|
||||
}
|
||||
|
||||
private class FoldingComparer : IComparer<NewFolding>
|
||||
|
||||
public void FoldToggle(int offset)
|
||||
{
|
||||
public int Compare(NewFolding x, NewFolding y)
|
||||
if (_foldingManager.AllFoldings == null)
|
||||
return;
|
||||
|
||||
var foldSection = _foldingManager.GetFoldingsContaining(offset);
|
||||
if (foldSection.Count > 0)
|
||||
foldSection[^1].IsFolded = !foldSection[^1].IsFolded;
|
||||
}
|
||||
|
||||
public void FoldAtLevel(int level = 0)
|
||||
{
|
||||
if (_foldingManager.AllFoldings == null)
|
||||
return;
|
||||
|
||||
foreach (var folding in _foldingManager.AllFoldings)
|
||||
{
|
||||
return x.StartOffset.CompareTo(y.StartOffset);
|
||||
if (folding.Tag is not CustomNewFolding realFolding) continue;
|
||||
if (realFolding.Level == level) folding.IsFolded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BraceFoldingStrategy : IFoldingStrategy
|
||||
public class BraceFoldingStrategy
|
||||
{
|
||||
private readonly char _opening;
|
||||
private readonly char _closing;
|
||||
|
||||
public BraceFoldingStrategy(TextEditor editor, char o, char c)
|
||||
public BraceFoldingStrategy(TextEditor editor)
|
||||
{
|
||||
_opening = o;
|
||||
_closing = c;
|
||||
UpdateFoldings(editor.Document);
|
||||
}
|
||||
|
||||
public IEnumerable<NewFolding> UpdateFoldings(TextDocument document)
|
||||
public IEnumerable<CustomNewFolding> UpdateFoldings(TextDocument document)
|
||||
{
|
||||
return CreateNewFoldings(document);
|
||||
}
|
||||
|
||||
public IEnumerable<NewFolding> CreateNewFoldings(ITextSource document)
|
||||
public IEnumerable<CustomNewFolding> CreateNewFoldings(ITextSource document)
|
||||
{
|
||||
var newFoldings = new List<NewFolding>();
|
||||
var newFoldings = new List<CustomNewFolding>();
|
||||
var startOffsets = new Stack<int>();
|
||||
var lastNewLineOffset = 0;
|
||||
var level = -1;
|
||||
|
||||
for (var i = 0; i < document.TextLength; i++)
|
||||
{
|
||||
var c = document.GetCharAt(i);
|
||||
if (c == _opening)
|
||||
switch (c)
|
||||
{
|
||||
startOffsets.Push(i);
|
||||
}
|
||||
else if (c == _closing && startOffsets.Count > 0)
|
||||
{
|
||||
var startOffset = startOffsets.Pop();
|
||||
if (startOffset < lastNewLineOffset)
|
||||
case '{' or '[':
|
||||
level++;
|
||||
startOffsets.Push(i);
|
||||
break;
|
||||
case '}' or ']' when startOffsets.Count > 0:
|
||||
{
|
||||
newFoldings.Add(new NewFolding(startOffset, i + 1));
|
||||
var startOffset = startOffsets.Pop();
|
||||
if (startOffset < lastNewLineOffset)
|
||||
{
|
||||
newFoldings.Add(new CustomNewFolding(startOffset, i + 1, level));
|
||||
}
|
||||
level--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (c is '\n' or '\r')
|
||||
{
|
||||
lastNewLineOffset = i + 1;
|
||||
case '\n' or '\r':
|
||||
lastNewLineOffset = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomNewFolding : NewFolding
|
||||
{
|
||||
public int Level { get; }
|
||||
|
||||
public CustomNewFolding(int start, int end, int level) : base(start, end)
|
||||
{
|
||||
Level = level;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{Level}] {StartOffset} -> {EndOffset}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
||||
xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
|
||||
xmlns:adonisControls="clr-namespace:AdonisUI.Controls;assembly=AdonisUI"
|
||||
WindowStartupLocation="CenterScreen" IconVisibility="Collapsed"
|
||||
WindowStartupLocation="CenterScreen" IconVisibility="Collapsed" PreviewKeyDown="OnPreviewKeyDown"
|
||||
Width="{Binding Source={x:Static SystemParameters.MaximizedPrimaryScreenWidth}, Converter={converters:RatioConverter}, ConverterParameter='0.40'}">
|
||||
<adonisControls:AdonisWindow.Resources>
|
||||
<ResourceDictionary>
|
||||
|
|
|
|||
|
|
@ -67,6 +67,22 @@ namespace FModel.Views.Resources.Controls
|
|||
_ => fontSize
|
||||
};
|
||||
}
|
||||
|
||||
private void OnPreviewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.J when Keyboard.IsKeyDown(Key.K) && Keyboard.Modifiers.HasFlag(ModifierKeys.Control):
|
||||
_manager.UnfoldAll();
|
||||
break;
|
||||
case Key.L when Keyboard.IsKeyDown(Key.K) && Keyboard.Modifiers.HasFlag(ModifierKeys.Control):
|
||||
_manager.FoldToggle(MyAvalonEditor.CaretOffset);
|
||||
break;
|
||||
case >= Key.D0 and <= Key.D9 when Keyboard.IsKeyDown(Key.K) && Keyboard.Modifiers.HasFlag(ModifierKeys.Control):
|
||||
_manager.FoldAtLevel(int.Parse(e.Key.ToString()[1].ToString()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouseHoverStopped(object sender, MouseEventArgs e)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user