Skip to content

Commit

Permalink
Code editor fixes and improvements
Browse files Browse the repository at this point in the history
1) Code editor preserves caret position after compiling, between "Decompiled" and "Disassembled" tabs, and between the tabs.
2) The changes from the PR UnderminersTeam#1148.
3) A little performance improvement of "NameGenerator" and "NumberGenerator" (code editor instance is declared on class init).
  • Loading branch information
VladiStep committed Jan 10, 2023
1 parent 35f8652 commit 53a6e0d
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 43 deletions.
17 changes: 9 additions & 8 deletions UndertaleModTool/Editors/UndertaleCodeEditor.xaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<local:DataUserControl x:Class="UndertaleModTool.UndertaleCodeEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UndertaleModTool"
xmlns:undertale="clr-namespace:UndertaleModLib.Models;assembly=UndertaleModLib"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance undertale:UndertaleCode}" DataContextChanged="UserControl_DataContextChanged">
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UndertaleModTool"
xmlns:undertale="clr-namespace:UndertaleModLib.Models;assembly=UndertaleModLib"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance undertale:UndertaleCode}"
DataContextChanged="UserControl_DataContextChanged" Unloaded="DataUserControl_Unloaded">
<UserControl.CommandBindings>
<CommandBinding Command="{x:Static local:UndertaleCodeEditor.Compile}" Executed="Command_Compile" />
</UserControl.CommandBindings>
Expand Down
113 changes: 84 additions & 29 deletions UndertaleModTool/Editors/UndertaleCodeEditor.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,14 @@ public partial class UndertaleCodeEditor : DataUserControl
public bool DecompiledYet = false;
public bool DecompiledSkipped = false;
public SearchPanel DecompiledSearchPanel;
public static (int Caret, int Line) OverriddenDecompPos;

public bool DisassemblyFocused = false;
public bool DisassemblyChanged = false;
public bool DisassembledYet = false;
public bool DisassemblySkipped = false;
public SearchPanel DisassemblySearchPanel;
public static (int Caret, int Line) OverriddenDisasmPos;

public static RoutedUICommand Compile = new RoutedUICommand("Compile code", "Compile", typeof(UndertaleCodeEditor));

Expand Down Expand Up @@ -131,8 +133,8 @@ public UndertaleCodeEditor()

DecompiledEditor.Options.ConvertTabsToSpaces = true;

DecompiledEditor.TextArea.TextView.ElementGenerators.Add(new NumberGenerator());
DecompiledEditor.TextArea.TextView.ElementGenerators.Add(new NameGenerator());
DecompiledEditor.TextArea.TextView.ElementGenerators.Add(new NumberGenerator(this));
DecompiledEditor.TextArea.TextView.ElementGenerators.Add(new NameGenerator(this));

DecompiledEditor.TextArea.TextView.Options.HighlightCurrentLine = true;
DecompiledEditor.TextArea.TextView.CurrentLineBackground = new SolidColorBrush(Color.FromRgb(60, 60, 60));
Expand Down Expand Up @@ -162,7 +164,7 @@ public UndertaleCodeEditor()
}
}

DisassemblyEditor.TextArea.TextView.ElementGenerators.Add(new NameGenerator());
DisassemblyEditor.TextArea.TextView.ElementGenerators.Add(new NameGenerator(this));

DisassemblyEditor.TextArea.TextView.Options.HighlightCurrentLine = true;
DisassemblyEditor.TextArea.TextView.CurrentLineBackground = new SolidColorBrush(Color.FromRgb(60, 60, 60));
Expand All @@ -176,6 +178,12 @@ public UndertaleCodeEditor()
DisassemblyEditor.TextArea.SelectionCornerRadius = 0;
}

private void DataUserControl_Unloaded(object sender, RoutedEventArgs e)
{
OverriddenDecompPos = default;
OverriddenDisasmPos = default;
}

private void SearchPanel_LostFocus(object sender, RoutedEventArgs e)
{
SearchPanel panel = sender as SearchPanel;
Expand Down Expand Up @@ -231,8 +239,7 @@ private async void UserControl_DataContextChanged(object sender, DependencyPrope
CurrentDecompiled is not null && CurrentDecompiled != code)
{
DecompiledSkipped = true;
DecompiledEditor_LostFocus(sender, null);

await DecompiledLostFocusBody(sender, null);
}
else if (DisassemblyTab.IsSelected && DisassemblyFocused && DisassemblyChanged &&
CurrentDisassembled is not null && CurrentDisassembled != code)
Expand All @@ -241,9 +248,14 @@ private async void UserControl_DataContextChanged(object sender, DependencyPrope
DisassemblyEditor_LostFocus(sender, null);
}

DecompiledEditor_LostFocus(sender, null);
await DecompiledLostFocusBody(sender, null);
DisassemblyEditor_LostFocus(sender, null);

DecompiledYet = false;
DisassembledYet = false;
CurrentDecompiled = null;
CurrentDisassembled = null;

if (MainWindow.CodeEditorDecompile != Unstated) //if opened from the code search results "link"
{
if (MainWindow.CodeEditorDecompile == DontDecompile && code != CurrentDisassembled)
Expand Down Expand Up @@ -309,6 +321,21 @@ private void DisassembleCode(UndertaleCode code, bool first)

string text;

int caretOffset = 0;
int currLine = 1;
if (!first)
{
caretOffset = DisassemblyEditor.CaretOffset;
currLine = DisassemblyEditor.Document.GetLineByOffset(caretOffset).LineNumber;
}
else if (OverriddenDisasmPos != default)
{
caretOffset = OverriddenDisasmPos.Caret;
currLine = OverriddenDisasmPos.Line;

OverriddenDisasmPos = default;
}

DisassemblyEditor.TextArea.ClearSelection();
if (code.ParentEntry != null)
{
Expand All @@ -327,6 +354,16 @@ private void DisassembleCode(UndertaleCode code, bool first)

DisassemblyEditor.Document.BeginUpdate();
DisassemblyEditor.Document.Text = text;

if (caretOffset <= text.Length)
{
DisassemblyEditor.CaretOffset = caretOffset;
if (currLine != -1)
DisassemblyEditor.ScrollToLine(currLine);
else
DisassemblyEditor.ScrollToEnd();
}

DisassemblyEditor.Document.EndUpdate();

if (first)
Expand Down Expand Up @@ -398,7 +435,24 @@ private string UpdateGettextJSON(string json)
private async Task DecompileCode(UndertaleCode code, bool first, LoaderDialog existingDialog = null)
{
DecompiledEditor.IsReadOnly = true;

int caretOffset = 0;
int currLine = 1;
if (!first)
{
caretOffset = DecompiledEditor.CaretOffset;
currLine = DecompiledEditor.Document.GetLineByOffset(caretOffset).LineNumber;
}
else if (OverriddenDecompPos != default)
{
caretOffset = OverriddenDecompPos.Caret;
currLine = OverriddenDecompPos.Line;

OverriddenDecompPos = default;
}

DecompiledEditor.TextArea.ClearSelection();

if (code.ParentEntry != null)
{
DecompiledEditor.Text = "// This code entry is a reference to an anonymous function within " + code.ParentEntry.Name.Content + ", view it there";
Expand Down Expand Up @@ -539,6 +593,15 @@ private async Task DecompileCode(UndertaleCode code, bool first, LoaderDialog ex
CurrentLocals.Add(local.Name.Content);
}

if (caretOffset <= decompiled.Length)
{
DecompiledEditor.CaretOffset = caretOffset;
if (currLine != -1)
DecompiledEditor.ScrollToLine(currLine);
else
DecompiledEditor.ScrollToEnd();
}

if (existingDialog is not null) //if code was edited (and compiles after it)
{
dataa.GMLCacheChanged.Add(code.Name.Content);
Expand All @@ -547,10 +610,12 @@ private async Task DecompileCode(UndertaleCode code, bool first, LoaderDialog ex
openSaveDialog = mainWindow.IsSaving;
}
}

DecompiledEditor.Document.EndUpdate();
DecompiledEditor.IsReadOnly = false;
if (first)
DecompiledEditor.Document.UndoStack.ClearAll();

DecompiledChanged = false;

CurrentDecompiled = code;
Expand Down Expand Up @@ -796,10 +861,12 @@ private void DisassemblyEditor_LostFocus(object sender, RoutedEventArgs e)
// Based on https://stackoverflow.com/questions/28379206/custom-hyperlinks-using-avalonedit
public class NumberGenerator : VisualLineElementGenerator
{
readonly static Regex regex = new Regex(@"-?\d+\.?");
private static readonly Regex regex = new Regex(@"-?\d+\.?");
private readonly UndertaleCodeEditor codeEditorInst;

public NumberGenerator()
public NumberGenerator(UndertaleCodeEditor codeEditorInst)
{
this.codeEditorInst = codeEditorInst;
}

Match FindMatch(int startOffset, Regex r)
Expand Down Expand Up @@ -866,20 +933,13 @@ public override VisualLineElement ConstructElement(int offset)
var doc = CurrentContext.Document;
var textArea = CurrentContext.TextView.GetService(typeof(TextArea)) as TextArea;
var editor = textArea.GetService(typeof(TextEditor)) as TextEditor;
var parent = VisualTreeHelper.GetParent(editor);
do
{
if ((parent as FrameworkElement) is UserControl)
break;
parent = VisualTreeHelper.GetParent(parent);
} while (parent != null);
line.Clicked += (text) =>
{
if (text.EndsWith("."))
return;
if (int.TryParse(text, out int id))
{
(parent as UndertaleCodeEditor).DecompiledFocused = true;
codeEditorInst.DecompiledFocused = true;
UndertaleData data = mainWindow.Data;

List<UndertaleObject> possibleObjects = new List<UndertaleObject>();
Expand Down Expand Up @@ -920,7 +980,7 @@ public override VisualLineElement ConstructElement(int offset)
{
doc.Replace(line.ParentVisualLine.StartOffset + line.RelativeTextOffset,
text.Length, (obj as UndertaleNamedResource).Name.Content, null);
(parent as UndertaleCodeEditor).DecompiledChanged = true;
codeEditorInst.DecompiledChanged = true;
}
};
contextMenu.Items.Add(item);
Expand All @@ -935,7 +995,7 @@ public override VisualLineElement ConstructElement(int offset)
{
doc.Replace(line.ParentVisualLine.StartOffset + line.RelativeTextOffset,
text.Length, "0x" + id.ToString("X6"), null);
(parent as UndertaleCodeEditor).DecompiledChanged = true;
codeEditorInst.DecompiledChanged = true;
}
};
contextMenu.Items.Add(item);
Expand All @@ -952,7 +1012,7 @@ public override VisualLineElement ConstructElement(int offset)
{
doc.Replace(line.ParentVisualLine.StartOffset + line.RelativeTextOffset,
text.Length, myKey, null);
(parent as UndertaleCodeEditor).DecompiledChanged = true;
codeEditorInst.DecompiledChanged = true;
}
};
contextMenu.Items.Add(item);
Expand All @@ -971,10 +1031,12 @@ public override VisualLineElement ConstructElement(int offset)

public class NameGenerator : VisualLineElementGenerator
{
readonly static Regex regex = new Regex(@"[_a-zA-Z][_a-zA-Z0-9]*");
private static readonly Regex regex = new Regex(@"[_a-zA-Z][_a-zA-Z0-9]*");
private readonly UndertaleCodeEditor codeEditorInst;

public NameGenerator()
public NameGenerator(UndertaleCodeEditor codeEditorInst)
{
this.codeEditorInst = codeEditorInst;
}

Match FindMatch(int startOffset, Regex r)
Expand Down Expand Up @@ -1046,13 +1108,6 @@ public override VisualLineElement ConstructElement(int offset)
var doc = CurrentContext.Document;
var textArea = CurrentContext.TextView.GetService(typeof(TextArea)) as TextArea;
var editor = textArea.GetService(typeof(TextEditor)) as TextEditor;
var parent = VisualTreeHelper.GetParent(editor);
do
{
if ((parent as FrameworkElement) is UserControl)
break;
parent = VisualTreeHelper.GetParent(parent);
} while (parent != null);

// Process the content of this identifier/function
if (func)
Expand Down Expand Up @@ -1114,7 +1169,7 @@ public override VisualLineElement ConstructElement(int offset)
data.BuiltinList.GlobalArray.ContainsKey(m.Value))
return new ColorVisualLineText(m.Value, CurrentContext.VisualLine, m.Length,
new SolidColorBrush(Color.FromRgb(0x58, 0xE3, 0x5A)));
if ((parent as UndertaleCodeEditor).CurrentLocals.Contains(m.Value))
if (codeEditorInst.CurrentLocals.Contains(m.Value))
return new ColorVisualLineText(m.Value, CurrentContext.VisualLine, m.Length,
new SolidColorBrush(Color.FromRgb(0xFF, 0xF8, 0x99)));
return null;
Expand Down
36 changes: 32 additions & 4 deletions UndertaleModTool/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ public enum ScrollDirection
Left,
Right
}

// TODO: move this to the code editor
public static CodeEditorMode CodeEditorDecompile { get; set; } = CodeEditorMode.Unstated;

private int progressValue;
Expand Down Expand Up @@ -3234,6 +3236,9 @@ public void CloseTab(int tabIndex, bool addDefaultTab = true)

if (Tabs.Count == 0)
{
if (!closingTab.AutoClose)
CurrentTab.SaveTabContentState(DataEditor);

CurrentTabIndex = -1;
CurrentTab = null;

Expand All @@ -3250,6 +3255,8 @@ public void CloseTab(int tabIndex, bool addDefaultTab = true)
}
else
{
bool tabIsChanged = false;

for (int i = tabIndex; i < Tabs.Count; i++)
Tabs[i].TabIndex = i;

Expand All @@ -3262,8 +3269,14 @@ public void CloseTab(int tabIndex, bool addDefaultTab = true)
// switch to the last tab
currIndex = Tabs.Count - 1;
}
else if (currIndex != 0)
currIndex -= 1;
else
{
if (currIndex != 0)
currIndex -= 1;

tabIsChanged = true;
CurrentTab.SaveTabContentState(DataEditor);
}
}
else if (currIndex > tabIndex)
{
Expand All @@ -3273,7 +3286,15 @@ public void CloseTab(int tabIndex, bool addDefaultTab = true)
TabController.SelectionChanged += TabController_SelectionChanged;

CurrentTabIndex = currIndex;
CurrentTab = Tabs[CurrentTabIndex];
Tab newTab = Tabs[CurrentTabIndex];

if (tabIsChanged)
newTab.PrepareCodeEditor();

CurrentTab = newTab;

if (tabIsChanged)
_ = CurrentTab.RestoreTabContentState(DataEditor);
}
}
}
Expand Down Expand Up @@ -3303,10 +3324,17 @@ private void TabController_SelectionChanged(object sender, SelectionChangedEvent
{
if (TabController.SelectedIndex >= 0)
{
CurrentTab?.SaveTabContentState(DataEditor);

ScrollToTab(CurrentTabIndex);

CurrentTab = Tabs[CurrentTabIndex];
Tab newTab = Tabs[CurrentTabIndex];
newTab.PrepareCodeEditor();
CurrentTab = newTab;

UpdateObjectLabel(CurrentTab.CurrentObject);

_ = CurrentTab.RestoreTabContentState(DataEditor);
}
}

Expand Down
Loading

0 comments on commit 53a6e0d

Please sign in to comment.