编译器QWQ

This commit is contained in:
muqing 2024-08-13 18:47:12 +08:00
parent 66a3c6526f
commit 871e195315
55 changed files with 286 additions and 6774 deletions

View File

@ -5,8 +5,6 @@ VisualStudioVersion = 17.10.34928.147
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RustTools", "RustTools\RustTools.csproj", "{2B938A8C-2116-4961-A9D7-5A755FFC1943}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TextControlBox", "TextControlBox\TextControlBox.csproj", "{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -51,26 +49,6 @@ Global
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|x86.ActiveCfg = Release|x86
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|x86.Build.0 = Release|x86
{2B938A8C-2116-4961-A9D7-5A755FFC1943}.Release|x86.Deploy.0 = Release|x86
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|ARM.ActiveCfg = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|ARM.Build.0 = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|arm64.ActiveCfg = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|arm64.Build.0 = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|x64.ActiveCfg = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|x64.Build.0 = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|x86.ActiveCfg = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Debug|x86.Build.0 = Debug|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|Any CPU.Build.0 = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|ARM.ActiveCfg = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|ARM.Build.0 = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|arm64.ActiveCfg = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|arm64.Build.0 = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|x64.ActiveCfg = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|x64.Build.0 = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|x86.ActiveCfg = Release|Any CPU
{70FED101-CE0C-4B8E-90BD-DC56C2ACA86F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -103,81 +103,5 @@ public class EditorLoad
});
}
return list;
ExplorerItem folder1 = new ExplorerItem()
{
Name = "Work Documents",
Type = ExplorerItem.ExplorerItemType.Folder,
Children =
{
new ExplorerItem()
{
Name = "Functional Specifications",
Type = ExplorerItem.ExplorerItemType.Folder,
Children =
{
new ExplorerItem()
{
Name = "TreeView spec",
Type = ExplorerItem.ExplorerItemType.File,
}
}
},
new ExplorerItem()
{
Name = "Feature Schedule",
Type = ExplorerItem.ExplorerItemType.File,
},
new ExplorerItem()
{
Name = "Overall Project Plan",
Type = ExplorerItem.ExplorerItemType.File,
},
new ExplorerItem()
{
Name = "Feature Resources Allocation",
Type = ExplorerItem.ExplorerItemType.File,
}
}
};
ExplorerItem folder2 = new ExplorerItem()
{
Name = "Personal Folder",
Type = ExplorerItem.ExplorerItemType.Folder,
Children =
{
new ExplorerItem()
{
Name = "Home Remodel Folder",
Type = ExplorerItem.ExplorerItemType.Folder,
Children =
{
new ExplorerItem()
{
Name = "Contractor Contact Info",
Type = ExplorerItem.ExplorerItemType.File,
},
new ExplorerItem()
{
Name = "Paint Color Scheme",
Type = ExplorerItem.ExplorerItemType.File,
},
new ExplorerItem()
{
Name = "Flooring Woodgrain type",
Type = ExplorerItem.ExplorerItemType.File,
},
new ExplorerItem()
{
Name = "Kitchen Cabinet Style",
Type = ExplorerItem.ExplorerItemType.File,
}
}
}
}
};
list.Add(folder1);
list.Add(folder2);
return list;
}
}

View File

@ -0,0 +1,139 @@

using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml;
using RustTools.muqing;
using Windows.ApplicationModel.DataTransfer;
using Microsoft.UI.Xaml.Input;
using Windows.Storage;
using RustTools.Helpers;
using Microsoft.UI.Xaml.Media;
using Windows.Foundation;
namespace RustTools.Editor;
public class EditorTreeView: TreeView
{
public EditorTreeView()
{
//CanDragItems = false;
//CanReorderItems =false;
DragEnter += EditorTreeView_DragEnter;
DragItemsStarting += TreeView_DragItemsStarting;
DragItemsCompleted += EditorTreeView_DragItemsCompleted;
DragOver += TreeView_DragOver;
Drop += TreeView_Drop;
// 在构造函数中注册事件处理程序
}
private void EditorTreeView_DragEnter(object sender, DragEventArgs e){
gj.sc("EditorTreeView_DragEnter "+e);
}
private void TreeView_DragItemsStarting(TreeView sender, TreeViewDragItemsStartingEventArgs e)
{
//gj.sc("TreeView_DragItemsStarting"+e);
var items = e.Items.Cast<ExplorerItem>();
var firstItem = items.FirstOrDefault();
gj.sc(firstItem.Dir);
e.Data.SetData("path", firstItem.Dir);
e.Data.RequestedOperation = DataPackageOperation.Move; // Use Copy to avoid moving items
}
private void EditorTreeView_DragItemsCompleted(TreeView sender, TreeViewDragItemsCompletedEventArgs e) {
var items = e.Items.Cast<ExplorerItem>();
var firstItem = items.FirstOrDefault();
gj.sc("放下了 " + firstItem.Dir);
}
/// <summary>
/// 如果是shift则开启多选状态
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void treeView_KeyDown(object sender, KeyRoutedEventArgs e)
{
// 检查是否按下了Shift键
if (e.Key == Windows.System.VirtualKey.Shift)
{
gj.sc(e.Key);
// 启用多选模式
SelectionMode = TreeViewSelectionMode.Multiple;
}
}
private void treeView_KeyUp(object sender, KeyRoutedEventArgs e)
{
// 检查是否松开了Shift键
if (e.Key == Windows.System.VirtualKey.Shift)
{ // 清除当前多选模式下选中的项目
var selectedItems = SelectedItems.ToList();
foreach (var item in selectedItems)
{
SelectedItems.Remove(item);
}
gj.sc("取消");
// 取消多选模式
SelectionMode = TreeViewSelectionMode.Single;
//treeView.SelectedItems.Clear();
}
}
/// <summary>
/// 其他窗口的文件夹拖过来的例子
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TreeView_DragOver(object sender, DragEventArgs e)
{
gj.sc(e);
// Allow dragging but prevent reordering
if (e.DataView.Contains(StandardDataFormats.StorageItems))
{
e.AcceptedOperation = DataPackageOperation.Move; // Use Copy to avoid reordering
e.Handled = true;
}
}
/// <summary>
/// 其他文件夹拖过来的放下事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void TreeView_Drop(object sender, DragEventArgs e)
{
gj.sc("TreeView_Drop: " + e);
// Handle drop event if needed but prevent reordering
if (e.DataView.Contains(StandardDataFormats.StorageItems))
{
var storageItems = await e.DataView.GetStorageItemsAsync();
// 获取目标文件夹,即拖放的位置
// 获取目标位置
var treeView = sender as TreeView;
var data = await e.DataView.GetDataAsync("path");
gj.sc(data);
foreach (var item in storageItems)
{
if (item is StorageFolder folder)
{
// 移动文件夹
gj.sc(folder.Path+"-->");
//var newFolder = await folder.MoveAsync(targetFolder, folder.Name, NameCollisionOption.ReplaceExisting);
}
else if (item is StorageFile file)
{
// 移动文件
//var newFile = await file.MoveAsync(targetFolder, file.Name, NameCollisionOption.ReplaceExisting);
}
}
e.Handled = true;
}
}
}

View File

@ -4,6 +4,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controlpages="using:RustTools.Editor"
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:RustTools"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -41,17 +42,11 @@
FileTemplate="{StaticResource FileTemplate}"
FolderTemplate="{StaticResource FolderTemplate}" />
<TabViewItem x:Key="FileTab">
<TextBox
x:Name="MyTextBox"
Height="200"
AcceptsReturn="True"
TextWrapping="Wrap" />
</TabViewItem>
</Page.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
@ -73,72 +68,49 @@
Grid.Column="0"
Margin="16,0,0,0" />
</Grid>
<ScrollViewer
x:Name="scrollview"
Grid.Row="2"
Grid.Column="0"
Width="300"
Margin="0,9,0,6"
Padding="0,0,16,0"
HorizontalScrollBarVisibility="Visible"
HorizontalScrollMode="Auto"
IsHorizontalRailEnabled="True"
IsHorizontalScrollChainingEnabled="True">
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<TreeView
<controlpages:EditorTreeView
Name="treeView"
Grid.Row="2"
Grid.Column="0"
DoubleTapped="treeView_DoubleTapped"
ItemInvoked="TreeView_ItemInvoked"
ItemTemplateSelector="{StaticResource ExplorerItemTemplateSelector}"
ItemsSource="{x:Bind DataSource}"
KeyDown="treeView_KeyDown"
KeyUp="treeView_KeyUp"
ScrollViewer.IsVerticalRailEnabled="False"
SelectionMode="Single" />
</ScrollViewer>
<ScrollViewer
<controls:PropertySizer
Grid.Row="1"
Grid.Column="1"
HorizontalScrollBarVisibility="Visible"
HorizontalScrollMode="Auto"
IsHorizontalRailEnabled="True"
IsHorizontalScrollChainingEnabled="True">
Binding="{x:Bind scrollview.Width, Mode=TwoWay}"
Maximum="350"
Minimum="200"
Visibility="Visible" />
<Grid
x:Name="gridedit"
Grid.Row="1"
Grid.Column="1">
Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TabView
x:Name="tabview"
Grid.Row="0"
Height="auto"
IsAddTabButtonVisible="False"
TabCloseRequested="TabView_TabCloseRequested"
TabItemsSource="{x:Bind TabViewList}" />
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox
Grid.Column="0"
Margin="0,0,10,0"
Background="Transparent"
ItemsSource="{x:Bind lineNumberList}"
ScrollViewer.IsVerticalRailEnabled="False">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Padding" Value="0" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Name="listboxtext" Text="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<RichEditBox
x:Name="editor"
Grid.Column="1"
Background="Transparent"
TextChanged="editor_TextChanged" />
</Grid>
</ScrollViewer>
</Grid>
</Page>
</windowex:WindowEx>

View File

@ -1,7 +1,9 @@
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Metadata;
using Microsoft.UI;
@ -18,8 +20,7 @@ namespace RustTools.Editor;
/// </summary>
public sealed partial class EditorWin : WindowEx
{
private readonly ObservableCollection<string> lineNumberList = new();
private readonly ObservableCollection<TabViewItem> TabViewList = new();
//目录列表
public ObservableCollection<ExplorerItem> DataSource=new ();
public EditorWin()
@ -44,40 +45,13 @@ public sealed partial class EditorWin : WindowEx
Title=directoryInfo.Name;
TitleText.Text = directoryInfo.Name;
Closed += EditorWin_Closed;
var v = wj.dqwb("D:\\steam\\steamapps\\common\\Rusted Warfare\\mods\\units\\赤道·联合进攻0.9补丁版0.2\\侵蚀者共和国\\指挥中心\\corrode_command.ini");
editor.Document.SetText(Microsoft.UI.Text.TextSetOptions.None,v);
// 获取第一个段落
//listboxtext
gj.sc(editor.Document.Selection.CharacterFormat.Size);
TextLine();
}
private void editor_TextChanged(object sender, RoutedEventArgs e)
{
TextLine();
}
public void TextLine()
{
lineNumberList.Clear();
editor.Document.GetText(Microsoft.UI.Text.TextGetOptions.NoHidden, out var a);
var lineCount = a.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None).Length;
if (lineCount < 1)
{
return;
}
for (var i = 1; i <= lineCount; i++)
{
lineNumberList.Add((i).ToString());
}
}
//用户有没有保存
private bool IsSave = true;
private ContentDialog? ClosedDialog;
private ContentDialog? ClosedDialog = null;
private async void EditorWin_Closed(object sender, WindowEventArgs e)
{
if (IsSave == false)
@ -122,11 +96,18 @@ public sealed partial class EditorWin : WindowEx
var myWndId = Win32Interop.GetWindowIdFromWindow(hWnd);
return Microsoft.UI.Windowing.AppWindow.GetFromWindowId(myWndId);
}
private void TreeView_ItemInvoked(TreeView sender, TreeViewItemInvokedEventArgs args)
/// <summary>
/// 选中事件
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void TreeView_ItemInvoked(TreeView sender, TreeViewItemInvokedEventArgs e)
{
// 获取当前选中的项
// 获取被点击的项
var invokedItem = args.InvokedItem;
var invokedItem = e.InvokedItem;
// 检查是否重复选择
if (sender.SelectedItem is ExplorerItem selectedItem && invokedItem != null && selectedItem == invokedItem)
{
@ -143,85 +124,52 @@ public sealed partial class EditorWin : WindowEx
}
}
private void TreeView_DragItemsStarting(TreeView sender, TreeViewDragItemsStartingEventArgs args)
private void TabView_TabCloseRequested(TabView sender, TabViewTabCloseRequestedEventArgs args)
{
args.Cancel = true;
// 设置拖动的数据
var items = args.Items.Cast<ExplorerItem>();
var v = items.ToList()[0];
args.Data.SetData("TreeViewItems", v.Dir);
args.Data.RequestedOperation = DataPackageOperation.Move;
TabViewList.Remove(args.Tab);
}
//在拖动项目悬停在 TreeView 上时,为放置操作提供视觉反馈。
private void TreeView_DragOver(object sender, DragEventArgs e)
{
// 检查是否存在 "TreeViewItems" 数据
gj.sc("aaaaaa");
if (e.DataView.Contains("TreeViewItems"))
{
e.AcceptedOperation = DataPackageOperation.Move; // 允许将文件夹拖放
}
else
{
gj.sc("No");
e.AcceptedOperation = DataPackageOperation.None; // 不接受拖放操作
}
}
//处理项目放置的逻辑,将文件或文件夹移动到新的位置。
private async void TreeView_Drop(object sender, DragEventArgs e)
{
gj.sc(e);
// 获取拖动的数据
if (e.DataView.Contains("TreeViewItems"))
{
// 确保数据不为空
if (await e.DataView.GetDataAsync("TreeViewItems") is string Dir)
{
gj.sc(Dir);
// 获取放置位置的 TreeViewItem
var treeView = sender as TreeView;
ExplorerItem v = treeView.DataContext is ExplorerItem;
//var dropPosition = e.GetPosition(treeView);
//data.Name
gj.sc(v.Name);
}
}
}
private IList<object> initialSelectedItems;
/// <summary>
/// 如果是shift则开启多选状态
/// 双击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void treeView_KeyDown(object sender, KeyRoutedEventArgs e)
private void treeView_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
{
// 检查是否按下了Shift键
if (e.Key == Windows.System.VirtualKey.Shift)
gj.sc(e.OriginalSource);
var treeViewItem = e.OriginalSource as Grid;
if (treeViewItem == null) { return; }
if (treeViewItem.DataContext is not ExplorerItem explorerItem) { return; }
if (explorerItem.Type == ExplorerItem.ExplorerItemType.File)
{
gj.sc(e.Key);
// 启用多选模式
treeView.SelectionMode = TreeViewSelectionMode.Multiple;
}
}
private void treeView_KeyUp(object sender, KeyRoutedEventArgs e)
{
// 检查是否松开了Shift键
if (e.Key == Windows.System.VirtualKey.Shift)
{ // 清除当前多选模式下选中的项目
var selectedItems = treeView.SelectedItems.ToList();
foreach (var item in selectedItems)
{
treeView.SelectedItems.Remove(item);
}
gj.sc("取消");
// 取消多选模式
treeView.SelectionMode = TreeViewSelectionMode.Single;
//treeView.SelectedItems.Clear();
}
}
private void tabView_TabCloseRequested(TabView sender, TabViewTabCloseRequestedEventArgs args)
// 查找特定的 TabViewItem
var tabViewItemToFind = TabViewList.FirstOrDefault(item => (item as TabViewItem)?.Tag.ToString() == explorerItem.Dir) as TabViewItem;
// 获取 TabViewItem 的索引位置
if (tabViewItemToFind != null)
{
sender.TabItems.Remove(args.Tab);
tabview.SelectedIndex = TabViewList.IndexOf(tabViewItemToFind);
return;
}
var fileInfo = new FileInfo(explorerItem.Dir);
//var name = Path.GetFileNameWithoutExtension(fileInfo.FullName);
var newItem = new TabViewItem()
{
Tag = explorerItem.Dir,
// 获取文件名,不包含扩展名
Header = fileInfo.Name,
IconSource = new Microsoft.UI.Xaml.Controls.SymbolIconSource() { Symbol = Symbol.Document }
};
//if(tabview.TabItems.)
var v = wj.dqwb(explorerItem.Dir);
var textControlBox = new RichEditBox();
//textControlBox.Height = Height;
textControlBox.Document.SetText(Microsoft.UI.Text.TextSetOptions.None, v);
newItem.Content = textControlBox;
TabViewList.Insert(0, newItem);
tabview.SelectedIndex = 0;
}
}
}

View File

@ -0,0 +1,66 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>RustTools</RootNamespace>
<Platform>x64</Platform>
<Platforms>x86;x64;arm64</Platforms>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
<AssemblyName>RustTools</AssemblyName>
<ApplicationManifest>app.manifest</ApplicationManifest>
<PackageIcon>tool.png</PackageIcon>
<ApplicationIcon>Assets\WindowIcon.ico</ApplicationIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<DefaultLanguage>zh-cn</DefaultLanguage>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
<PackageCertificateThumbprint>3386EC79D3BB9691D0A8DA634167500B242E109D</PackageCertificateThumbprint>
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
<AppxSymbolPackageEnabled>False</AppxSymbolPackageEnabled>
<GenerateTestArtifacts>True</GenerateTestArtifacts>
<AppxBundle>Never</AppxBundle>
<AppxPackageDir>D:\RustTools</AppxPackageDir>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.0.240109" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.231008000" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
<PackageReference Include="RestClient" Version="3.1024.23771" />
<PackageReference Include="RestSharp" Version="111.4.0" />
<PackageReference Include="System.Management" Version="8.0.0" />
<PackageReference Include="WinUIEx" Version="2.3.2" />
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240227000" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.3233" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TextControlBox\TextControlBox.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />
</ItemGroup>
</Project>

View File

@ -35,6 +35,8 @@
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.0.240109" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.231008000" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
@ -54,9 +56,6 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TextControlBox\TextControlBox.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />

View File

@ -1,28 +0,0 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the three default line endings: LF (Line Feed), CRLF (Carriage Return + Line Feed), and CR (Carriage Return).
/// </summary>
/// <remarks>
/// The LineEnding enum represents the different line ending formats that can be used in the textbox.
/// The enum defines three values: LF, CRLF, and CR, corresponding to the different line ending formats.
/// - LF: Represents the Line Feed character '\n' used for line breaks in Unix-based systems.
/// - CRLF: Represents the Carriage Return + Line Feed sequence '\r\n' used for line breaks in Windows-based systems.
/// - CR: Represents the Carriage Return character '\r' used for line breaks in older Macintosh systems.
/// </remarks>
public enum LineEnding
{
/// <summary>
/// Line Feed ('\n')
/// </summary>
LF,
/// <summary>
/// Carriage Return + Line Feed ('\r\n')
/// </summary>
CRLF,
/// <summary>
/// Carriage Return ('\r')
/// </summary>
CR
}
}

View File

@ -1,7 +0,0 @@
namespace TextControlBoxNS
{
internal enum LineMoveDirection
{
Up, Down
}
}

View File

@ -1,39 +0,0 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the result of a search operation in the textbox.
/// </summary>
public enum SearchResult
{
/// <summary>
/// The target text was found during the search operation.
/// </summary>
Found,
/// <summary>
/// The target text was not found during the search operation.
/// </summary>
NotFound,
/// <summary>
/// The search input provided for the search operation was invalid or empty.
/// </summary>
InvalidInput,
/// <summary>
/// The search operation reached the beginning of the text without finding the target text.
/// </summary>
ReachedBegin,
/// <summary>
/// The search operation reached the end of the text without finding the target text.
/// </summary>
ReachedEnd,
/// <summary>
/// The search operation was attempted, but the search was not started.
/// </summary>
SearchNotOpened
}
}

View File

@ -1,13 +0,0 @@
using Windows.UI;
namespace TextControlBoxNS.Extensions
{
internal static class ColorExtension
{
public static Windows.UI.Color ToMediaColor(this System.Drawing.Color drawingColor)
{
return Windows.UI.Color.FromArgb(drawingColor.A, drawingColor.R, drawingColor.G, drawingColor.B);
}
public static string ToHex(this Color c) => $"#{c.R:X2}{c.G:X2}{c.B:X2}";
}
}

View File

@ -1,10 +0,0 @@
namespace TextControlBoxNS.Extensions
{
internal static class IntExtension
{
public static bool IsInRange(this int value, int start, int count)
{
return value >= start && value <= start + count;
}
}
}

View File

@ -1,137 +0,0 @@
using Collections.Pooled;
using System;
using System.Collections.Generic;
using System.Linq;
using TextControlBoxNS.Helper;
namespace TextControlBoxNS.Extensions
{
internal static class ListExtension
{
private static int CurrentLineIndex = 0;
public static string GetLineText(this PooledList<string> list, int index)
{
if (list.Count == 0)
return "";
if (index == -1 && list.Count > 0)
return list[list.Count - 1];
index = index >= list.Count ? list.Count - 1 : index > 0 ? index : 0;
return list[index];
}
public static int GetLineLength(this PooledList<string> list, int index)
{
return GetLineText(list, index).Length;
}
public static void AddLine(this PooledList<string> list, string content = "")
{
list.Add(content);
}
public static void SetLineText(this PooledList<string> list, int line, string text)
{
if (line == -1)
line = list.Count - 1;
line = Math.Clamp(line, 0, list.Count - 1);
list[line] = text;
}
public static string GetCurrentLineText(this PooledList<string> list)
{
return list[CurrentLineIndex < list.Count ? CurrentLineIndex : list.Count - 1 < 0 ? 0 : list.Count - 1];
}
public static void SetCurrentLineText(this PooledList<string> list, string text)
{
list[CurrentLineIndex < list.Count ? CurrentLineIndex : list.Count - 1] = text;
}
public static int CurrentLineLength(this PooledList<string> list)
{
return GetCurrentLineText(list).Length;
}
public static void UpdateCurrentLine(this PooledList<string> _, int currentLine)
{
CurrentLineIndex = currentLine;
}
public static void String_AddToEnd(this PooledList<string> list, int line, string add)
{
list[line] = list[line] + add;
}
public static void InsertOrAdd(this PooledList<string> list, int index, string lineText)
{
if (index >= list.Count || index == -1)
list.Add(lineText);
else
list.Insert(index, lineText);
}
public static void InsertOrAddRange(this PooledList<string> list, IEnumerable<string> lines, int index)
{
if (index >= list.Count)
list.AddRange(lines);
else
list.InsertRange(index < 0 ? 0 : index, lines);
}
public static void InsertNewLine(this PooledList<string> list, int index, string content = "")
{
list.InsertOrAdd(index, content);
}
public static void DeleteAt(this PooledList<string> list, int index)
{
if (index >= list.Count)
index = list.Count - 1 < 0 ? list.Count - 1 : 0;
list.RemoveAt(index);
list.TrimExcess();
}
private static IEnumerable<string> GetLines_Small(this PooledList<string> totalLines, int start, int count)
{
var res = ListHelper.CheckValues(totalLines, start, count);
for (int i = 0; i < res.Count; i++)
{
yield return totalLines[i + res.Index];
}
}
public static IEnumerable<string> GetLines(this PooledList<string> totalLines, int start, int count)
{
//use different algorithm for small amount of lines:
if (start + count < 400)
{
return GetLines_Small(totalLines, start, count);
}
return totalLines.Skip(start).Take(count);
}
public static string GetString(this IEnumerable<string> lines, string NewLineCharacter)
{
return string.Join(NewLineCharacter, lines);
}
public static void Safe_RemoveRange(this PooledList<string> totalLines, int index, int count)
{
var res = ListHelper.CheckValues(totalLines, index, count);
totalLines.RemoveRange(res.Index, res.Count);
totalLines.TrimExcess();
//clear up the memory of the list when more than 1mio items are removed
if (res.Count > 1_000_000)
ListHelper.GCList(totalLines);
}
public static string[] GetLines(this string[] lines, int start, int count)
{
return lines.Skip(start).Take(count).ToArray();
}
public static void SwapLines(this PooledList<string> lines, int originalindex, int newindex)
{
string oldLine = lines.GetLineText(originalindex);
lines.SetLineText(originalindex, lines.GetLineText(newindex));
lines.SetLineText(newindex, oldLine);
}
}
}

View File

@ -1,16 +0,0 @@
using Windows.Foundation;
namespace TextControlBoxNS.Extensions
{
internal static class PointExtension
{
public static Point Subtract(this Point point, double subtractX, double subtractY)
{
return new Point(point.X - subtractX, point.Y - subtractY);
}
public static Point Subtract(this Point point, Point subtract)
{
return new Point(point.X - subtract.X, point.Y - subtract.Y);
}
}
}

View File

@ -1,63 +0,0 @@
using System;
using System.Text.RegularExpressions;
using TextControlBoxNS.Helper;
namespace TextControlBoxNS.Extensions
{
internal static class StringExtension
{
public static string RemoveFirstOccurence(this string value, string removeString)
{
int index = value.IndexOf(removeString, StringComparison.Ordinal);
return index < 0 ? value : value.Remove(index, removeString.Length);
}
public static string AddToEnd(this string text, string add)
{
return text + add;
}
public static string AddToStart(this string text, string add)
{
return add + text;
}
public static string AddText(this string text, string add, int position)
{
if (position < 0)
position = 0;
if (position >= text.Length || text.Length <= 0)
return text + add;
else
return text.Insert(position, add);
}
public static string SafeRemove(this string text, int start, int count = -1)
{
if (start >= text.Length || start < 0)
return text;
if (count <= -1)
return text.Remove(start);
else
return text.Remove(start, count);
}
public static bool Contains(this string text, SearchParameter parameter)
{
if (parameter.WholeWord)
return Regex.IsMatch(text, parameter.SearchExpression, RegexOptions.Compiled);
if (parameter.MatchCase)
return text.Contains(parameter.Word, StringComparison.Ordinal);
else
return text.Contains(parameter.Word, StringComparison.OrdinalIgnoreCase);
}
public static string Safe_Substring(this string text, int index, int count = -1)
{
if (index >= text.Length)
return "";
else if (count == -1)
return text.Substring(index);
else
return text.Substring(index, count);
}
}
}

View File

@ -1,41 +0,0 @@
using Microsoft.Graphics.Canvas.UI.Xaml;
using Windows.UI.Core;
namespace TextControlBoxNS.Helper
{
internal class CanvasHelper
{
public CanvasControl Canvas_Selection = null;
public CanvasControl Canvas_Linenumber = null;
public CanvasControl Canvas_Text = null;
public CanvasControl Canvas_Cursor = null;
public CanvasHelper(CanvasControl canvas_selection, CanvasControl canvas_linenumber, CanvasControl canvas_text, CanvasControl canvas_cursor)
{
this.Canvas_Text = canvas_text;
this.Canvas_Linenumber = canvas_linenumber;
this.Canvas_Cursor = canvas_cursor;
this.Canvas_Selection = canvas_selection;
}
public void UpdateCursor()
{
Canvas_Cursor.Invalidate();
}
public void UpdateText()
{
//TODO: Utils.ChangeCursor(CoreCursorType.IBeam);
Canvas_Text.Invalidate();
}
public void UpdateSelection()
{
Canvas_Selection.Invalidate();
}
public void UpdateAll()
{
UpdateText();
UpdateSelection();
UpdateCursor();
}
}
}

View File

@ -1,41 +0,0 @@
using Microsoft.UI.Xaml.Controls;
using System;
namespace TextControlBoxNS.Helper
{
internal class FlyoutHelper
{
public MenuFlyout MenuFlyout;
public FlyoutHelper(TextControlBox sender)
{
CreateFlyout(sender);
}
public void CreateFlyout(TextControlBox sender)
{
MenuFlyout = new MenuFlyout();
MenuFlyout.Items.Add(CreateItem(() => { sender.Copy(); }, "Copy", Symbol.Copy, "Ctrl + C"));
MenuFlyout.Items.Add(CreateItem(() => { sender.Paste(); }, "Paste", Symbol.Paste, "Ctrl + V"));
MenuFlyout.Items.Add(CreateItem(() => { sender.Cut(); }, "Cut", Symbol.Cut, "Ctrl + X"));
MenuFlyout.Items.Add(new MenuFlyoutSeparator());
MenuFlyout.Items.Add(CreateItem(() => { sender.Undo(); }, "Undo", Symbol.Undo, "Ctrl + Z"));
MenuFlyout.Items.Add(CreateItem(() => { sender.Redo(); }, "Redo", Symbol.Redo, "Ctrl + Y"));
}
public MenuFlyoutItem CreateItem(Action action, string text, Symbol icon, string key)
{
var item = new MenuFlyoutItem
{
Text = text,
KeyboardAcceleratorTextOverride = key,
Icon = new SymbolIcon { Symbol = icon }
};
item.Click += delegate
{
action();
};
return item;
}
}
}

View File

@ -1,13 +0,0 @@
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
namespace TextControlBoxNS.Helper
{
internal class InputHandlerControl : TextBox
{
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
return;
}
}
}

View File

@ -1,75 +0,0 @@
using Collections.Pooled;
using System;
using System.Linq;
namespace TextControlBoxNS.Helper
{
internal class ListHelper
{
public struct ValueResult
{
public ValueResult(int index, int count)
{
this.Index = index;
this.Count = count;
}
public int Index;
public int Count;
}
public static ValueResult CheckValues(PooledList<string> totalLines, int index, int count)
{
if (index >= totalLines.Count)
{
index = totalLines.Count - 1 < 0 ? 0 : totalLines.Count - 1;
count = 0;
}
if (index + count >= totalLines.Count)
{
int difference = totalLines.Count - index;
if (difference >= 0)
count = difference;
}
if (count < 0)
count = 0;
if (index < 0)
index = 0;
return new ValueResult(index, count);
}
public static void GCList(PooledList<string> totalLines)
{
int id = GC.GetGeneration(totalLines);
GC.Collect(id, GCCollectionMode.Forced);
}
public static void Clear(PooledList<string> totalLines, bool addNewLine = false)
{
totalLines.Clear();
GCList(totalLines);
if (addNewLine)
totalLines.Add("");
}
public static string GetLinesAsString(PooledList<string> lines, string newLineCharacter)
{
return string.Join(newLineCharacter, lines);
}
public static string[] GetLinesFromString(string content, string newLineCharacter)
{
return content.Split(newLineCharacter);
}
public static string[] CreateLines(string[] lines, int start, string beginning, string end)
{
if (start > 0)
lines = lines.Skip(start).ToArray();
lines[0] = beginning + lines[0];
if (lines.Length - 1 > 0)
lines[lines.Length - 1] = lines[lines.Length - 1] + end;
return lines;
}
}
}

View File

@ -1,218 +0,0 @@
using Collections.Pooled;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using TextControlBoxNS.Extensions;
using TextControlBoxNS.Text;
namespace TextControlBoxNS.Helper
{
internal class SearchHelper
{
public int CurrentSearchLine = 0;
public int CurrentSearchArrayIndex = 0;
public int OldSearchArrayIndex = 0;
public int[] MatchingSearchLines = null;
public bool IsSearchOpen = false;
public SearchParameter SearchParameter = null;
public MatchCollection CurrentLineMatches = null;
private int RegexIndexInLine = 0;
private int CheckIndexValue(int i)
{
return i >= MatchingSearchLines.Length ? MatchingSearchLines.Length - 1 : i < 0 ? 0 : i;
}
public InternSearchResult FindNext(PooledList<string> totalLines, CursorPosition cursorPosition)
{
if (IsSearchOpen && MatchingSearchLines != null && MatchingSearchLines.Length > 0)
{
CurrentSearchLine = cursorPosition.LineNumber;
int indexInList = Array.IndexOf(MatchingSearchLines, CurrentSearchLine);
//When in a line without a match search for the next line with a match
if (indexInList == -1)
{
for (int i = 0; i < MatchingSearchLines.Length; i++)
{
if (MatchingSearchLines[i] > CurrentSearchLine)
{
CurrentSearchArrayIndex = i - 1 < 0 ? 0 : i - 1;
CurrentSearchLine = MatchingSearchLines[CurrentSearchArrayIndex];
break;
}
}
}
else
{
CurrentSearchArrayIndex = indexInList;
CurrentSearchLine = MatchingSearchLines[CurrentSearchArrayIndex];
if (OldSearchArrayIndex != CurrentSearchArrayIndex)
{
OldSearchArrayIndex = CurrentSearchArrayIndex;
CurrentLineMatches = null;
}
}
//Search went through all matches in the current line:
if (CurrentLineMatches == null || RegexIndexInLine >= CurrentLineMatches.Count)
{
RegexIndexInLine = 0;
//back at start
if (CurrentSearchLine < MatchingSearchLines[MatchingSearchLines.Length - 1])
{
CurrentSearchArrayIndex++;
CurrentSearchLine = cursorPosition.LineNumber = MatchingSearchLines[CurrentSearchArrayIndex];
CurrentLineMatches = Regex.Matches(totalLines[CurrentSearchLine], SearchParameter.SearchExpression);
}
else
return new InternSearchResult(SearchResult.ReachedEnd, null);
}
RegexIndexInLine = Math.Clamp(RegexIndexInLine, 0, CurrentLineMatches.Count - 1);
RegexIndexInLine++;
if (RegexIndexInLine > CurrentLineMatches.Count || RegexIndexInLine < 0)
return new InternSearchResult(SearchResult.NotFound, null);
return new InternSearchResult(SearchResult.Found, new TextSelection(
new CursorPosition(CurrentLineMatches[RegexIndexInLine - 1].Index, cursorPosition.LineNumber),
new CursorPosition(CurrentLineMatches[RegexIndexInLine - 1].Index + CurrentLineMatches[RegexIndexInLine - 1].Length, cursorPosition.LineNumber)));
}
return new InternSearchResult(SearchResult.NotFound, null);
}
public InternSearchResult FindPrevious(PooledList<string> totalLines, CursorPosition cursorPosition)
{
if (IsSearchOpen && MatchingSearchLines != null)
{
//Find the next linnenumber with a match if the line is not in the array of matching lines
CurrentSearchLine = cursorPosition.LineNumber;
int indexInList = Array.IndexOf(MatchingSearchLines, CurrentSearchLine);
if (indexInList == -1)
{
//Find the first line with matches which is smaller than the current line:
var lines = MatchingSearchLines.Where(x => x < CurrentSearchLine);
if (lines.Count() < 1)
{
return new InternSearchResult(SearchResult.ReachedBegin, null);
}
CurrentSearchArrayIndex = Array.IndexOf(MatchingSearchLines, lines.Last());
CurrentSearchLine = MatchingSearchLines[CurrentSearchArrayIndex];
CurrentLineMatches = null;
}
else
{
CurrentSearchArrayIndex = indexInList;
CurrentSearchLine = MatchingSearchLines[CurrentSearchArrayIndex];
if (OldSearchArrayIndex != CurrentSearchArrayIndex)
{
OldSearchArrayIndex = CurrentSearchArrayIndex;
CurrentLineMatches = null;
}
}
//Search went through all matches in the current line:
if (CurrentLineMatches == null || RegexIndexInLine < 0)
{
//back at start
if (CurrentSearchLine == MatchingSearchLines[0])
{
return new InternSearchResult(SearchResult.ReachedBegin, null);
}
if (CurrentSearchLine < MatchingSearchLines[MatchingSearchLines.Length - 1])
{
CurrentSearchLine = cursorPosition.LineNumber = MatchingSearchLines[CheckIndexValue(CurrentSearchArrayIndex - 1)];
CurrentLineMatches = Regex.Matches(totalLines[CurrentSearchLine], SearchParameter.SearchExpression);
RegexIndexInLine = CurrentLineMatches.Count - 1;
CurrentSearchArrayIndex--;
}
}
if (CurrentLineMatches == null)
return new InternSearchResult(SearchResult.NotFound, null);
RegexIndexInLine = Math.Clamp(RegexIndexInLine, 0, CurrentLineMatches.Count - 1);
//RegexIndexInLine--;
if (RegexIndexInLine >= CurrentLineMatches.Count || RegexIndexInLine < 0)
return new InternSearchResult(SearchResult.NotFound, null);
return new InternSearchResult(SearchResult.Found, new TextSelection(
new CursorPosition(CurrentLineMatches[RegexIndexInLine].Index, cursorPosition.LineNumber),
new CursorPosition(CurrentLineMatches[RegexIndexInLine].Index + CurrentLineMatches[RegexIndexInLine--].Length, cursorPosition.LineNumber)));
}
return new InternSearchResult(SearchResult.NotFound, null);
}
public void UpdateSearchLines(PooledList<string> totalLines)
{
MatchingSearchLines = FindIndexes(totalLines);
}
public SearchResult BeginSearch(PooledList<string> totalLines, string word, bool matchCase, bool wholeWord)
{
SearchParameter = new SearchParameter(word, wholeWord, matchCase);
UpdateSearchLines(totalLines);
if (word == "" || word == null)
return SearchResult.InvalidInput;
//A result was found
if (MatchingSearchLines.Length > 0)
{
IsSearchOpen = true;
}
return MatchingSearchLines.Length > 0 ? SearchResult.Found : SearchResult.NotFound;
}
public void EndSearch()
{
IsSearchOpen = false;
MatchingSearchLines = null;
}
private int[] FindIndexes(PooledList<string> totalLines)
{
List<int> results = new List<int>();
for (int i = 0; i < totalLines.Count; i++)
{
if (totalLines[i].Contains(SearchParameter))
results.Add(i);
};
return results.ToArray();
}
}
internal class SearchParameter
{
public SearchParameter(string word, bool wholeWord = false, bool matchCase = false)
{
this.Word = word;
this.WholeWord = wholeWord;
this.MatchCase = matchCase;
if (wholeWord)
SearchExpression += @"\b" + (matchCase ? "" : "(?i)") + Regex.Escape(word) + @"\b";
else
SearchExpression += (matchCase ? "" : "(?i)") + Regex.Escape(word);
}
public bool WholeWord { get; set; }
public bool MatchCase { get; set; }
public string Word { get; set; }
public string SearchExpression { get; set; } = "";
}
internal struct InternSearchResult
{
public InternSearchResult(SearchResult result, TextSelection selection)
{
this.Result = result;
this.Selection = selection;
}
public TextSelection Selection;
public SearchResult Result;
}
}

View File

@ -1,74 +0,0 @@
using Collections.Pooled;
using System;
namespace TextControlBoxNS.Helper
{
internal class TabSpaceHelper
{
private int _NumberOfSpaces = 4;
private string OldSpaces = " ";
public int NumberOfSpaces
{
get => _NumberOfSpaces;
set
{
if (value != _NumberOfSpaces)
{
OldSpaces = Spaces;
_NumberOfSpaces = value;
Spaces = new string(' ', _NumberOfSpaces);
}
}
}
public bool UseSpacesInsteadTabs = false;
public string TabCharacter { get => UseSpacesInsteadTabs ? Spaces : Tab; }
private string Spaces = " ";
private string Tab = "\t";
public void UpdateNumberOfSpaces(PooledList<string> totalLines)
{
ReplaceSpacesToSpaces(totalLines);
}
public void UpdateTabs(PooledList<string> totalLines)
{
if (UseSpacesInsteadTabs)
ReplaceTabsToSpaces(totalLines);
else
ReplaceSpacesToTabs(totalLines);
}
public string UpdateTabs(string input)
{
if (UseSpacesInsteadTabs)
return Replace(input, Tab, Spaces);
return Replace(input, Spaces, Tab);
}
private void ReplaceSpacesToSpaces(PooledList<string> totalLines)
{
for (int i = 0; i < totalLines.Count; i++)
{
totalLines[i] = Replace(totalLines[i], OldSpaces, Spaces);
}
}
private void ReplaceSpacesToTabs(PooledList<string> TotalLines)
{
for (int i = 0; i < TotalLines.Count; i++)
{
TotalLines[i] = Replace(TotalLines[i], Spaces, Tab);
}
}
private void ReplaceTabsToSpaces(PooledList<string> totalLines)
{
for (int i = 0; i < totalLines.Count; i++)
{
totalLines[i] = Replace(totalLines[i], "\t", Spaces);
}
}
public string Replace(string input, string find, string replace)
{
return input.Replace(find, replace, StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@ -1,64 +0,0 @@
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.UI.Xaml.Media;
using Windows.Foundation;
namespace TextControlBoxNS.Helper
{
internal class TextLayoutHelper
{
public static CanvasTextLayout CreateTextResource(ICanvasResourceCreatorWithDpi resourceCreator, CanvasTextLayout textLayout, CanvasTextFormat textFormat, string text, Size targetSize)
{
if (textLayout != null)
textLayout.Dispose();
textLayout = CreateTextLayout(resourceCreator, textFormat, text, targetSize);
textLayout.Options = CanvasDrawTextOptions.EnableColorFont;
return textLayout;
}
public static CanvasTextFormat CreateCanvasTextFormat(float zoomedFontSize, FontFamily fontFamily)
{
return CreateCanvasTextFormat(zoomedFontSize, zoomedFontSize + 2, fontFamily);
}
public static CanvasTextFormat CreateCanvasTextFormat(float zoomedFontSize, float lineSpacing, FontFamily fontFamily)
{
CanvasTextFormat textFormat = new CanvasTextFormat()
{
FontSize = zoomedFontSize,
HorizontalAlignment = CanvasHorizontalAlignment.Left,
VerticalAlignment = CanvasVerticalAlignment.Top,
WordWrapping = CanvasWordWrapping.NoWrap,
LineSpacing = lineSpacing,
};
textFormat.IncrementalTabStop = zoomedFontSize * 3; //default 137px
textFormat.FontFamily = fontFamily.Source;
textFormat.TrimmingGranularity = CanvasTextTrimmingGranularity.None;
textFormat.TrimmingSign = CanvasTrimmingSign.None;
return textFormat;
}
public static CanvasTextLayout CreateTextLayout(ICanvasResourceCreator resourceCreator, CanvasTextFormat textFormat, string text, Size canvasSize)
{
return new CanvasTextLayout(resourceCreator, text, textFormat, (float)canvasSize.Width, (float)canvasSize.Height);
}
public static CanvasTextLayout CreateTextLayout(ICanvasResourceCreator resourceCreator, CanvasTextFormat textFormat, string text, float width, float height)
{
return new CanvasTextLayout(resourceCreator, text, textFormat, width, height);
}
public static CanvasTextFormat CreateLinenumberTextFormat(float fontSize, FontFamily fontFamily)
{
CanvasTextFormat textFormat = new CanvasTextFormat()
{
FontSize = fontSize,
HorizontalAlignment = CanvasHorizontalAlignment.Right,
VerticalAlignment = CanvasVerticalAlignment.Top,
WordWrapping = CanvasWordWrapping.NoWrap,
LineSpacing = fontSize + 2,
};
textFormat.FontFamily = fontFamily.Source;
textFormat.TrimmingGranularity = CanvasTextTrimmingGranularity.None;
textFormat.TrimmingSign = CanvasTrimmingSign.None;
return textFormat;
}
}
}

View File

@ -1,160 +0,0 @@
using Collections.Pooled;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.UI.Xaml;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using TextControlBoxNS.Extensions;
using Windows.Foundation;
using Windows.System;
using Windows.UI.Core;
using Windows.UI.Popups;
namespace TextControlBoxNS.Helper
{
internal class Utils
{
public static Size MeasureTextSize(CanvasDevice device, string text, CanvasTextFormat textFormat, float limitedToWidth = 0.0f, float limitedToHeight = 0.0f)
{
CanvasTextLayout layout = new CanvasTextLayout(device, text, textFormat, limitedToWidth, limitedToHeight);
return new Size(layout.DrawBounds.Width, layout.DrawBounds.Height);
}
public static Size MeasureLineLenght(CanvasDevice device, string text, CanvasTextFormat textFormat)
{
if (text.Length == 0)
return new Size(0, 0);
//If the text starts with a tab or a whitespace, replace it with the last character of the line, to
//get the actual width of the line, because tabs and whitespaces at the beginning are not counted to the lenght
//Do the same for the end
double placeholderWidth = 0;
if (text.StartsWith('\t') || text.StartsWith(' '))
{
text = text.Insert(0, "|");
placeholderWidth += MeasureTextSize(device, "|", textFormat).Width;
}
if (text.EndsWith('\t') || text.EndsWith(' '))
{
text = text += "|";
placeholderWidth += MeasureTextSize(device, "|", textFormat).Width;
}
CanvasTextLayout layout = new CanvasTextLayout(device, text, textFormat, 0, 0);
return new Size(layout.DrawBounds.Width - placeholderWidth, layout.DrawBounds.Height);
}
//Get the longest line in the textbox
public static int GetLongestLineIndex(PooledList<string> totalLines)
{
int longestIndex = 0;
int oldLenght = 0;
for (int i = 0; i < totalLines.Count; i++)
{
var lenght = totalLines[i].Length;
if (lenght > oldLenght)
{
longestIndex = i;
oldLenght = lenght;
}
}
return longestIndex;
}
public static int GetLongestLineLength(string text)
{
var splitted = text.Split("\n");
int oldLenght = 0;
for (int i = 0; i < splitted.Length; i++)
{
var lenght = splitted[i].Length;
if (lenght > oldLenght)
{
oldLenght = lenght;
}
}
return oldLenght;
}
public static bool CursorPositionsAreEqual(CursorPosition first, CursorPosition second)
{
return first.LineNumber == second.LineNumber && first.CharacterPosition == second.CharacterPosition;
}
public static string[] SplitAt(string text, int index)
{
string first = index < text.Length ? text.SafeRemove(index) : text;
string second = index < text.Length ? text.Safe_Substring(index) : "";
return new string[] { first, second };
}
public static int CountCharacters(PooledList<string> totalLines)
{
int count = 0;
for (int i = 0; i < totalLines.Count; i++)
{
count += totalLines[i].Length + 1;
}
return count - 1;
}
public static bool IsKeyPressed(VirtualKey key)
{
return Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(key).HasFlag(CoreVirtualKeyStates.Down);
}
public static async Task<bool> IsOverTextLimit(int textLength)
{
if (textLength > 100000000)
{
await new MessageDialog("Current textlimit is 100 million characters, but your file has " + textLength + " characters").ShowAsync();
return true;
}
return false;
}
public static void Benchmark(Action action, string text)
{
Stopwatch sw = new Stopwatch();
sw.Start();
action.Invoke();
sw.Stop();
Debug.WriteLine(text + " took " + sw.ElapsedMilliseconds + "::" + sw.ElapsedTicks);
}
public static ApplicationTheme ConvertTheme(ElementTheme theme)
{
switch (theme)
{
case ElementTheme.Light: return ApplicationTheme.Light;
case ElementTheme.Dark: return ApplicationTheme.Dark;
case ElementTheme.Default:
var defaultTheme = new Windows.UI.ViewManagement.UISettings();
return defaultTheme.GetColorValue(Windows.UI.ViewManagement.UIColorType.Background).ToString() == "#FF000000"
? ApplicationTheme.Dark : ApplicationTheme.Light;
default: return ApplicationTheme.Light;
}
}
public static Point GetTextboxstartingPoint(UIElement relativeTo)
{
return relativeTo.TransformToVisual(Window.Current.Content).TransformPoint(new Point(0, 0));
}
public static int CountLines(string text, string newLineCharacter)
{
return (text.Length - text.Replace(newLineCharacter, "").Length) / newLineCharacter.Length + 1;
}
public static Rect CreateRect(Rect rect, float marginLeft = 0, float marginTop = 0)
{
return new Rect(
new Point(
Math.Floor(rect.Left + marginLeft),//X
Math.Floor(rect.Top + marginTop)), //Y
new Point(
Math.Ceiling(rect.Right + marginLeft), //Width
Math.Ceiling(rect.Bottom + marginTop))); //Height
}
}
}

View File

@ -1,511 +0,0 @@
namespace TextControlBoxNS.Languages
{
internal class Batch : CodeLanguage
{
public Batch()
{
this.Name = "Batch";
this.Author = "Julius Kirsch";
this.Filter = new string[1] { ".bat" };
this.Description = "Syntax highlighting for Batch language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),
new SyntaxHighlights("(?i)(set|echo|for|pushd|popd|pause|exit|cd|if|else|goto|del)\\s", "#dd00dd", "#dd00dd"),
new SyntaxHighlights("(:.*)", "#00C000", "#ffff00"),
new SyntaxHighlights("(\\\".+?\\\"|\\'.+?\\')", "#00C000", "#ffff00"),
new SyntaxHighlights("(@|%)", "#dd0077", "#dd0077"),
new SyntaxHighlights("(\\*)", "#dd0077", "#dd0077"),
new SyntaxHighlights("((?i)rem.*)", "#888888", "#888888"),
};
}
}
internal class ConfigFile : CodeLanguage
{
public ConfigFile()
{
this.Name = "ConfigFile";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".ini" };
this.Description = "Syntax highlighting for configuration files";
this.AutoPairingPair = new AutoPairingPair[]
{
new AutoPairingPair("[", "]")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("[\\[\\]]", "#0000FF", "#0000FF"),
new SyntaxHighlights("\\[[\\t\\s]*(\\w+)[\\t\\s]*\\]", "#9900FF", "#9900FF"),
new SyntaxHighlights("(\\w+)\\=", "#DDDD00", "#DDDD00"),
new SyntaxHighlights("\\=(.+)", "#EE0000", "#EE0000"),
new SyntaxHighlights(";.*", "#888888", "#888888"),
};
}
}
internal class Cpp : CodeLanguage
{
public Cpp()
{
this.Name = "C++";
this.Author = "Julius Kirsch";
this.Filter = new string[6] { ".cpp", ".cxx", ".cc", ".hpp", ".h", ".c" };
this.Description = "Syntax highlighting for C++ language";
this.AutoPairingPair = new AutoPairingPair[5]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#00ff00"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#4455ff", "#ffbb00"),
new SyntaxHighlights("\\b(string|uint16_t|uint8_t|alignas|alignof|and|and_eq|asm|auto|bitand|bitor|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|false|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|not|not_eq|nullptr|operator|or|or_eq|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|true|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while|xor|xor_eq)\\b", "#dd00dd", "#dd00dd"),
new SyntaxHighlights("\\B#(define|elif|else|endif|error|ifndef|ifdef|if|import|include|line|pragma|region|undef|using)", "#bbbbbb", "#999999"),
new SyntaxHighlights("(\\\".+?\\\"|\\'.+?\\')", "#ffff00", "#ff000f"),
new SyntaxHighlights("\"[^\\n]*?\"", "#00CA00", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
};
}
}
internal class CSharp : CodeLanguage
{
public CSharp()
{
this.Name = "C#";
this.Author = "Julius Kirsch";
this.Filter = new string[1] { ".cs" };
this.Description = "Syntax highlighting for C# language";
this.AutoPairingPair = new AutoPairingPair[5]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#ff00ff", "#ff00ff"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#880088", "#ffbb00"),
new SyntaxHighlights("\\b(abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|external|false|final|finally|fixed|float|for|foreach|get|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|partial|private|protected|public|readonly|ref|return|sbyte|sealed|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|value|var|virtual|void|volatile|while)\\b", "#0066bb", "#00ffff"),
new SyntaxHighlights("\\b(List|Color|Console|Debug|Dictionary|Stack|Queue|GC)\\b", "#008000", "#ff9900"),
new SyntaxHighlights("\\b(try|catch|finally)\\b", "#9922ff", "#6666ff"),
new SyntaxHighlights("(#region)+(.*?)($|\n)", "#ff0000", "#ff0000", true),
new SyntaxHighlights("#endregion", "#ff0000", "#ff0000", true),
new SyntaxHighlights("\"[^\\n]*?\"", "#ff5500", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
};
}
}
internal class GCode : CodeLanguage
{
public GCode()
{
this.Name = "GCode";
this.Author = "Julius Kirsch";
this.Filter = new string[5] { ".ngc", ".tap", ".gcode", ".nc", ".cnc" };
this.Description = "Syntax highlighting for GCode language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\bY(?=([0-9]|(\\+|\\-)[0-9]))", "#00ff00", "#00ff00"),
new SyntaxHighlights("\\bX(?=([0-9]|(\\+|\\-)[0-9]))", "#ff0000", "#ff0000"),
new SyntaxHighlights("\\bZ(?=([0-9]|(\\+|\\-)[0-9]))", "#0077ff", "#0077ff"),
new SyntaxHighlights("\\bA(?=([0-9]|(\\+|\\-)[0-9]))", "#ff00ff", "#ff00ff"),
new SyntaxHighlights("\\b(E|F)(?=([0-9]|(\\+|\\-)[0-9]))", "#ffAA00", "#ffAA00"),
new SyntaxHighlights("\\b(S|T)(?=([0-9]|(\\+|\\-)[0-9]))", "#ffff00", "#ffff00"),
new SyntaxHighlights("([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?", "#ff00ff", "#9f009f"),
new SyntaxHighlights("[G|M][0-999].*?[\\s|\\n]", "#00aaaa", "#00ffff"),
new SyntaxHighlights("(;|\\/\\/|\\brem\\b).*", "#888888", "#888888"),
};
}
}
internal class HexFile : CodeLanguage
{
public HexFile()
{
this.Name = "HexFile";
this.Author = "Finn Freitag";
this.Filter = new string[2] { ".hex", ".bin" };
this.Description = "Syntaxhighlighting for hex and binary code.";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\:", "#FFFF00", "#FFFF00"),
new SyntaxHighlights("\\:([0-9A-Fa-f]{2})", "#00FF00", "#00FF00"),
new SyntaxHighlights("\\:[0-9A-Fa-f]{2}([0-9A-Fa-f]{4})", "#00FF00", "#00FF00"),
new SyntaxHighlights("\\:[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})", "#FF5500", "#FF5500"),
new SyntaxHighlights("\\:[0-9A-Fa-f]{8}([0-9A-Fa-f]*)[0-9A-Fa-f]{2}", "#00FFFF", "#00FFFF"),
new SyntaxHighlights("\\:[0-9A-Fa-f]{8}[0-9A-Fa-f]*([0-9A-Fa-f]{2})", "#666666", "#666666"),
new SyntaxHighlights("//.*", "#666666", "#666666"),
new SyntaxHighlights("[^0-9A-Fa-f\\:\\n]", "#FF0000", "#FF0000", false, false, true),
};
}
}
internal class Html : CodeLanguage
{
public Html()
{
this.Name = "Html";
this.Author = "Julius Kirsch";
this.Filter = new string[2] { ".html", ".htm" };
this.Description = "Syntax highlighting for Html language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),
new SyntaxHighlights("[-A-Za-z_]+\\=", "#00CA00", "#Ff0000"),
new SyntaxHighlights("<([^ >!\\/]+)[^>]*>", "#969696", "#0099ff"),
new SyntaxHighlights("<+[/]+[a-zA-Z0-9:?\\-_]+>", "#969696", "#0099ff"),
new SyntaxHighlights("<[a-zA-Z0-9:?\\-]+?.*\\/>", "#969696", "#0099ff"),
new SyntaxHighlights("\"[^\\n]*?\"", "#00CA00", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("[0-9]+(px|rem|em|vh|vw|px|pt|pc|in|mm|cm|deg|%)", "#ff00ff", "#dd00dd"),
new SyntaxHighlights("<!--[\\s\\S]*?-->", "#888888", "#888888"),
};
}
}
internal class Java : CodeLanguage
{
public Java()
{
this.Name = "Java";
this.Author = "Julius Kirsch";
this.Filter = new string[2] { ".java", ".class" };
this.Description = "Syntax highlighting for Java language";
this.AutoPairingPair = new AutoPairingPair[5]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#ff00ff", "#ff00ff"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#880088", "#ffbb00"),
new SyntaxHighlights("\\b(System.out|System|Math)\\b", "#008000", "#ff9900"),
new SyntaxHighlights("\\b(abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|try|void|volatile|while|exports|modle|non-sealed|open|opens|permits|provides|record|requires|sealed|to|transitive|uses|var|with|yield|true|false|null)\\b", "#0066bb", "#00ffff"),
new SyntaxHighlights("\"[^\\n]*?\"", "#ff5500", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
};
}
}
internal class Javascript : CodeLanguage
{
public Javascript()
{
this.Name = "Javascript";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".js" };
this.Description = "Syntax highlighting for Javascript language";
this.AutoPairingPair = new AutoPairingPair[6]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("`", "`"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\W", "#990033", "#CC0066"),
new SyntaxHighlights("(\\+|\\-|\\*|/|%|\\=|\\:|\\!|>|\\<|\\?|&|\\||\\~|\\^)", "#77FF77", "#77FF77"),
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#ff00ff", "#ff00ff"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#880088", "#ffbb00"),
new("\\b(goto|in|instanceof|static|arguments|public|do|else|const|function|class|return|let|eval|for|if|this|break|debugger|yield|extends|enum|continue|export|null|switch|private|new|throw|while|case|await|delete|super|default|void|var|protected|package|interface|false|typeof|implements|with|import|true)\\b", "#0066bb", "#00ffff"),
new SyntaxHighlights("\\b(document|window|screen)\\b", "#008000", "#33BB00"),
new SyntaxHighlights("\\b(try|catch|finally)\\b", "#9922ff", "#6666ff"),
new SyntaxHighlights("/[^\\n]*/i{0,1}", "#FFFF00", "#FFFF00"),
new SyntaxHighlights("[\"'][^\\n]*?[\"']", "#ff5500", "#00FF00"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
};
}
}
internal class INI : CodeLanguage
{
public INI()
{
Name = "INI";
Author = "Rust";
Filter = new string[1] { ".ini" };
Description = "Ini语法突出显示";
AutoPairingPair = new AutoPairingPair[]
{
new("[", "]"),
new(" ",":")
};
Highlights = new SyntaxHighlights[]
{
new("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),//数字?
//new("\\b(true|false)\\b","#00AADD", "#0099ff"),//bool值
new("\\[.*?\\]", "#e91e63", "#e91e63"),
new("(.*?):","#2196f3","#00ff00"),
new(":","#000000","#ffffff"),
new("\\b(false|true|if|=)\\b", "#0066bb", "#00ffff"),
new("##.*", "#888888", "#646464"),// 单行注释
};
}
}
internal class Json : CodeLanguage
{
public Json()
{
this.Name = "Json";
this.Author = "Julius Kirsch";
this.Filter = new string[1] { ".json" };
this.Description = "Syntax highlighting for Json language";
this.AutoPairingPair = new AutoPairingPair[4]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),
new SyntaxHighlights("(null|true|false)", "#00AADD", "#0099ff"),
new SyntaxHighlights("(,|{|}|\\[|\\])", "#969696", "#646464"),
new SyntaxHighlights("(\".+\")\\:", "#00CA00", "#dddd00"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("\"[^\\n]*?\"", "#00CA00", "#00FF00"),
};
}
}
internal class PHP : CodeLanguage
{
public PHP()
{
this.Name = "PHP";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".php" };
this.Description = "Syntax highlighting for PHP language";
this.AutoPairingPair = new AutoPairingPair[2]
{
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\<\\?php", "#FF0000", "#FF0000"),
new SyntaxHighlights("\\?\\>", "#FF0000", "#FF0000"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#3300FF", "#aa00FF"),
new SyntaxHighlights("\\b(echo|if|case|while|else|switch|foreach|function|default|break|null|true|false)\\b", "#0077FF", "#0077FF"),
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#ff00ff", "#ff00ff"),
new SyntaxHighlights("(\\+|\\-|\\*|/|%|\\=|\\:|\\!|>|\\<|\\?|&|\\||\\~|\\^)", "#77FF77", "#77FF77"),
new SyntaxHighlights("\\$\\w+", "#440044", "#FFBBFF"),
new SyntaxHighlights("\"[^\\n]*?\"", "#ff5500", "#00FF00"),
new SyntaxHighlights("\\'[^\\n]*?\\'", "#ff5500", "#00FF00"),
new SyntaxHighlights("\"/[^\\n]*/i{0,1}\"", "#ff5500", "#00FF00"),
new SyntaxHighlights("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", "#888888", "#646464"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
};
}
}
internal class QSharp : CodeLanguage
{
public QSharp()
{
this.Name = "QSharp";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".qs" };
this.Description = "Syntax highlighting for QSharp language";
this.AutoPairingPair = new AutoPairingPair[5]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\W", "#BB0000", "#BB0000"),
new SyntaxHighlights("\\/\\/.*", "#888888", "#646464"),
new SyntaxHighlights("\\b(namespace|open|operation|using|let|H|M|Reset|return)\\b", "#0066bb", "#00ffff"),
new SyntaxHighlights("\\b(Qubit|Result)\\b", "#00bb66", "#00ff00"),
};
}
}
internal class XML : CodeLanguage
{
public XML()
{
this.Name = "XML";
this.Author = "Julius Kirsch";
this.Filter = new string[2] { ".xml", ".xaml" };
this.Description = "Syntax highlighting for Xml language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),
new SyntaxHighlights("<([^ >!\\/]+)[^>]*>", "#969696", "#0099ff"),
new SyntaxHighlights("<+[/]+[a-zA-Z0-9:?\\-_]+>", "#969696", "#0099ff"),
new SyntaxHighlights("<[a-zA-Z0-9:?\\-]+?.*\\/>", "#969696", "#0099ff"),
new SyntaxHighlights("[-A-Za-z_]+\\=", "#00CA00", "#Ff0000"),
new SyntaxHighlights("\"[^\\n]*?\"", "#00CA00", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("<!--[\\s\\S]*?-->", "#888888", "#888888"),
};
}
}
internal class Python : CodeLanguage
{
public Python()
{
this.Name = "Python";
this.Author = "Julius Kirsch";
this.Filter = new string[1] { ".py" };
this.Description = "Syntax highlighting for Python language";
this.AutoPairingPair = new AutoPairingPair[6]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("`", "`"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\b([+-]?(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*))(?:[eE]([+-]?\\d+))?\\b", "#dd00dd", "#ff00ff"),
new SyntaxHighlights("\\b(and|as|assert|break|class|continue|def|del|elif|else|except|False|finally|for|from|global|if|import|in|is|lambda|None|nonlocal|not|or|pass|raise|return|True|try|while|with|yield)\\b", "#aa00cc", "#cc00ff"),
new SyntaxHighlights("(?<!(def\\s))(?<=^|\\s|.)[a-zA-Z_][\\w_]*(?=\\()", "#cc9900", "#ffbb00"),
new SyntaxHighlights("\"[^\\n]*?\"", "#ff5500", "#00FF00"),
new SyntaxHighlights("'[^\\n]*?'", "#00CA00", "#00FF00"),
new SyntaxHighlights("\\#.*", "#888888", "#646464"),
new SyntaxHighlights("\\\"\"\"(.|[\\r\\n])*\\\"\"\"", "#888888", "#646464"),
};
}
}
internal class CSV : CodeLanguage
{
public CSV()
{
this.Name = "CSV";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".csv" };
this.Description = "Syntax highlighting for CSV language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("[\\:\\,\\;]", "#1b9902", "#1b9902")
};
}
}
internal class LaTex : CodeLanguage
{
public LaTex()
{
this.Name = "LaTex";
this.Author = "Finn Freitag";
this.Filter = new string[2] { ".latex", ".tex" };
this.Description = "Syntax highlighting for LaTex language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\\\[a-z]+", "#0033aa", "#0088ff"),
new SyntaxHighlights("%.*", "#888888", "#646464"),
new SyntaxHighlights("[\\[\\]]", "#FFFF00", "#FFFF00"),
new SyntaxHighlights("[\\{\\}]", "#FF0000", "#FF0000"),
new SyntaxHighlights("\\$", "#00bb00", "#00FF00")
};
}
}
internal class TOML : CodeLanguage
{
public TOML()
{
this.Name = "TOML";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".toml" };
this.Description = "Syntax highlighting for TOML language";
this.AutoPairingPair = new AutoPairingPair[]
{
new AutoPairingPair("[", "]"),
new AutoPairingPair("\""),
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("\\[.*\\]", "#0000FF", "#0000FF"),
new SyntaxHighlights("\\[[\\t\\s]*(\\w+)[\\t\\s]*\\]", "#9900FF", "#9900FF"),
new SyntaxHighlights("(\\w+)[\\s\\t]*\\=", "#DDDD00", "#DDDD00"),
new SyntaxHighlights("\\=\\s+(.+)", "#EE0000", "#EE0000"),
new SyntaxHighlights("[\\[\\]]", "#FFFF00", "#FFFF00"),
new SyntaxHighlights("\\b(true|false)\\b", "#00bb66", "#00ff00"),
new SyntaxHighlights("[\"'][^\\n]*?[\"']", "#D69D84", "#D69D84"),
new SyntaxHighlights("#.*", "#888888", "#888888")
};
}
}
internal class Markdown : CodeLanguage
{
public Markdown()
{
this.Name = "Markdown";
this.Author = "Finn Freitag";
this.Filter = new string[1] { ".md" };
this.Description = "Syntax highlighting for Markdown language";
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("[>~\"'`\\-\\+|\\^\\!_]", "#FF0000", "#FF0000"),
new SyntaxHighlights("#", "#0000FF", "#0000FF"),
new SyntaxHighlights("\\*.*\\*", "#000000", "#FFFFFF", false, true),
new SyntaxHighlights("_.*_", "#000000", "#FFFFFF", false, true),
new SyntaxHighlights("\\*\\*.*\\*\\*", "#000000", "#FFFFFF", true),
new SyntaxHighlights("__.*__", "#000000", "#FFFFFF", true),
new SyntaxHighlights("\\d+\\.", "#00FF00", "#00FF00"),
new SyntaxHighlights("[\\[\\]\\(\\)]", "#FFFF00", "#FFFF00")
};
}
}
internal class CSS : CodeLanguage
{
public CSS()
{
this.Name = "CSS";
this.Author = "Julius Kirsch";
this.Filter = new string[2] { ".css", ".scss" };
this.Description = "Syntax highlighting for CSS language";
this.AutoPairingPair = new AutoPairingPair[5]
{
new AutoPairingPair("{", "}"),
new AutoPairingPair("[", "]"),
new AutoPairingPair("(", ")"),
new AutoPairingPair("\""),
new AutoPairingPair("\'")
};
this.Highlights = new SyntaxHighlights[]
{
new SyntaxHighlights("[a-zA-Z-]+.*;", "#ff5500", "#00ffff"),//properties
new SyntaxHighlights("\\b([a-zA-Z_-][a-zA-Z0-9_-]*)(?=\\()", "#bb00bb", "#00ff99"),//functions
new SyntaxHighlights(":[a-z].*(?={)", "#0033ff", "#fffd00"),//pseudo classes/elements
new SyntaxHighlights("(.|#|^).*\\s*{", "#227700", "#44ff00"),//classname
new SyntaxHighlights("(?<=\\d)(?:px|%|em|rem|in|cm|mm|pt|pc|ex|ch|vw|vh|vmin|vmax|ms|s)", "#cc0000", "#ff0000"),//units
new SyntaxHighlights("\\b-?\\d+(?:\\.\\d+)?", "#0000ff", "#cc00ff"),//numbers
new SyntaxHighlights("@([^ ]+)", "#8800ff", "#ff0000"),//first word after the @
new SyntaxHighlights("#[0-9A-Fa-f]{1,8}\\b", "#00bb55", "#cc00ff"),//hexadecimal
new SyntaxHighlights("(\".+?\"|\'.+?\')", "#00aaff", "#ff8800"),//strings
new SyntaxHighlights("(;|:|{|}|,)", "#777777", "#bbbbbb"),//special characters
new SyntaxHighlights("\\/\\*(.|\\n)*?\\*\\/", "#555555", "#888888"),//comments
};
}
}
}

View File

@ -1,45 +0,0 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents a pair of characters used for auto-pairing in text.
/// </summary>
public class AutoPairingPair
{
/// <summary>
/// Initializes a new instance of the AutoPairingPair class with the same value for both the opening and closing characters.
/// </summary>
/// <param name="value">The character value to be used for both opening and closing.</param>
public AutoPairingPair(string value)
{
this.Value = this.Pair = value;
}
/// <summary>
/// Initializes a new instance of the AutoPairingPair class with different values for the opening and closing characters.
/// </summary>
/// <param name="value">The character value to be used as the opening character.</param>
/// <param name="pair">The character value to be used as the closing character.</param>
public AutoPairingPair(string value, string pair)
{
this.Value = value;
this.Pair = pair;
}
/// <summary>
/// Checks if the provided input contains the opening character of the pair.
/// </summary>
/// <param name="input">The input string to check for the opening character.</param>
/// <returns>True if the input contains the opening character; otherwise, false.</returns>
public bool Matches(string input) => input.Contains(this.Value);
/// <summary>
/// Gets or sets the character value used for the opening part of the auto-pairing pair.
/// </summary>
public string Value { get; set; }
/// <summary>
/// Gets or sets the character value used for the closing part of the auto-pairing pair.
/// </summary>
public string Pair { get; set; }
}
}

View File

@ -1,37 +0,0 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the font style settings for a code element in the text.
/// </summary>
public class CodeFontStyle
{
/// <summary>
/// Initializes a new instance of the CodeFontStyle class with the specified font style settings.
/// </summary>
/// <param name="underlined">true if the code element should be displayed with an underline; otherwise, false.</param>
/// <param name="italic">true if the code element should be displayed in italic font; otherwise, false.</param>
/// <param name="bold">true if the code element should be displayed in bold font; otherwise, false.</param>
public CodeFontStyle(bool underlined, bool italic, bool bold)
{
this.Italic = italic;
this.Bold = bold;
this.Underlined = underlined;
}
/// <summary>
/// Gets or sets a value indicating whether the code element should be displayed with an underline.
/// </summary>
public bool Underlined { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the code element should be displayed in bold font.
/// </summary>
public bool Bold { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the code element should be displayed in italic font.
/// </summary>
public bool Italic { get; set; }
}
}

View File

@ -1,39 +0,0 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents a code language configuration used for syntax highlighting and auto-pairing in the text content.
/// </summary>
public class CodeLanguage
{
/// <summary>
/// Gets or sets the name of the code language.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the description of the code language.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Gets or sets an array of file filters for the code language.
/// </summary>
public string[] Filter { get; set; }
/// <summary>
/// Gets or sets the author of the code language definition.
/// </summary>
public string Author { get; set; }
/// <summary>
/// Gets or sets an array of syntax highlights for the code language.
/// </summary>
public SyntaxHighlights[] Highlights { get; set; }
/// <summary>
/// Gets or sets an array of auto-pairing pairs for the code language.
/// </summary>
public AutoPairingPair[] AutoPairingPair { get; set; }
}
}

View File

@ -1,116 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TextControlBoxNS.Languages;
namespace TextControlBoxNS
{
/// <summary>
/// Represents the unique identifiers for different code languages used for syntax highlighting.
/// </summary>
public enum CodeLanguageId
{
INI,
/// <summary>
/// Identifier for Batch code language.
/// </summary>
Batch,
/// <summary>
/// Identifier for C++ code language.
/// </summary>
Cpp,
/// <summary>
/// Identifier for C# code language.
/// </summary>
CSharp,
/// <summary>
/// Identifier for configuration file code language.
/// </summary>
ConfigFile,
/// <summary>
/// Identifier for CSS code language.
/// </summary>
CSS,
/// <summary>
/// Identifier for CSV code language.
/// </summary>
CSV,
/// <summary>
/// Identifier for GCode code language.
/// </summary>
GCode,
/// <summary>
/// Identifier for HexFile code language.
/// </summary>
HexFile,
/// <summary>
/// Identifier for HTML code language.
/// </summary>
Html,
/// <summary>
/// Identifier for Java code language.
/// </summary>
Java,
/// <summary>
/// Identifier for JavaScript code language.
/// </summary>
Javascript,
/// <summary>
/// Identifier for JSON code language.
/// </summary>
Json,
/// <summary>
/// Identifier for LaTeX code language.
/// </summary>
Latex,
/// <summary>
/// Identifier for Markdown code language.
/// </summary>
Markdown,
/// <summary>
/// Identifier for PHP code language.
/// </summary>
PHP,
/// <summary>
/// Identifier for Python code language.
/// </summary>
Python,
/// <summary>
/// Identifier for Q# code language.
/// </summary>
QSharp,
/// <summary>
/// Identifier for TOML code language.
/// </summary>
TOML,
/// <summary>
/// Identifier for XML code language.
/// </summary>
XML,
/// <summary>
/// Identifier for no code language.
/// </summary>
None,
}
}

View File

@ -1,51 +0,0 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the position of the cursor in the textbox.
/// </summary>
/// <remarks>
/// The CursorPosition class stores the position of the cursor within the textbox.
/// It consists of two properties: CharacterPosition and LineNumber.
/// The CharacterPosition property indicates the index of the cursor within the current line (zero-based index).
/// The LineNumber property represents the line number on which the cursor is currently positioned (zero-based index).
/// </remarks>
public class CursorPosition
{
internal CursorPosition(int characterPosition = 0, int lineNumber = 0)
{
this.CharacterPosition = characterPosition;
this.LineNumber = lineNumber;
}
internal CursorPosition(CursorPosition currentCursorPosition)
{
if (currentCursorPosition == null)
return;
this.CharacterPosition = currentCursorPosition.CharacterPosition;
this.LineNumber = currentCursorPosition.LineNumber;
}
/// <summary>
/// Gets the character position of the cursor within the current line.
/// </summary>
public int CharacterPosition { get; internal set; } = 0;
/// <summary>
/// Gets the line number in which the cursor is currently positioned.
/// </summary>
public int LineNumber { get; internal set; } = 0;
internal void AddToCharacterPos(int add)
{
CharacterPosition += add;
}
internal void SubtractFromCharacterPos(int subtract)
{
CharacterPosition -= subtract;
if (CharacterPosition < 0)
CharacterPosition = 0;
}
internal static CursorPosition ChangeLineNumber(CursorPosition currentCursorPosition, int lineNumber)
{
return new CursorPosition(currentCursorPosition.CharacterPosition, lineNumber);
}
}
}

View File

@ -1,43 +0,0 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the size of the cursor in the textbox.
/// </summary>
public class CursorSize
{
/// <summary>
/// Creates a new instance of the CursorSize class
/// </summary>
/// <param name="width">The width of the cursor</param>
/// <param name="height">The height of the cursor</param>
/// <param name="offsetX">The x-offset from the actual cursor position</param>
/// <param name="offsetY">The y-offset from the actual cursor position</param>
public CursorSize(float width = 0, float height = 0, float offsetX = 0, float offsetY = 0)
{
this.Width = width;
this.Height = height;
this.OffsetX = offsetX;
this.OffsetY = offsetY;
}
/// <summary>
/// The width of the cursor
/// </summary>
public float Width { get; private set; }
/// <summary>
/// The height of the cursor
/// </summary>
public float Height { get; private set; }
/// <summary>
/// The left/right offset from the actual cursor position
/// </summary>
public float OffsetX { get; private set; }
/// <summary>
/// The top/bottom offset from the actual cursor position
/// </summary>
public float OffsetY { get; private set; }
}
}

View File

@ -1,11 +0,0 @@
namespace TextControlBoxNS
{
internal class JsonCodeLanguage
{
public string Name { get; set; }
public string Description { get; set; }
public string Filter { get; set; }
public string Author { get; set; }
public SyntaxHighlights[] Highlights;
}
}

View File

@ -1,29 +0,0 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the result of a JSON load operation for a code language in the textbox.
/// </summary>
public class JsonLoadResult
{
/// <summary>
/// Initializes a new instance of the JsonLoadResult class with the specified loading status and CodeLanguage.
/// </summary>
/// <param name="succeed">true if the loading operation succeeded; otherwise, false.</param>
/// <param name="codeLanguage">The CodeLanguage loaded from the JSON data.</param>
public JsonLoadResult(bool succeed, CodeLanguage codeLanguage)
{
this.Succeed = succeed;
this.CodeLanguage = codeLanguage;
}
/// <summary>
/// Gets or sets a value indicating whether the loading operation succeeded.
/// </summary>
public bool Succeed { get; set; }
/// <summary>
/// Gets or sets the CodeLanguage that was loaded from the JSON data.
/// </summary>
public CodeLanguage CodeLanguage { get; set; }
}
}

View File

@ -1,40 +0,0 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the position of a scrollbar, containing the horizontal and vertical scroll positions.
/// </summary>
public class ScrollBarPosition
{
/// <summary>
/// Initializes a new instance of the ScrollBarPosition class with the provided values.
/// </summary>
/// <param name="scrollBarPosition">The existing ScrollBarPosition object from which to copy the values.</param>
public ScrollBarPosition(ScrollBarPosition scrollBarPosition)
{
this.ValueX = scrollBarPosition.ValueX;
this.ValueY = scrollBarPosition.ValueY;
}
/// <summary>
/// Creates a new instance of the ScrollBarPosition class
/// </summary>
/// <param name="valueX">The horizontal amount scrolled</param>
/// <param name="valueY">The vertical amount scrolled</param>
public ScrollBarPosition(double valueX = 0, double valueY = 0)
{
this.ValueX = valueX;
this.ValueY = valueY;
}
/// <summary>
/// The amount scrolled horizontally
/// </summary>
public double ValueX { get; set; }
/// <summary>
/// The amount scrolled vertically
/// </summary>
public double ValueY { get; set; }
}
}

View File

@ -1,28 +0,0 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the class that will be returned by the SelectionChanged event of the TextControlBox.
/// </summary>
public class SelectionChangedEventHandler
{
/// <summary>
/// Represents the position of the cursor within the current line.
/// </summary>
public int CharacterPositionInLine { get; set; }
/// <summary>
/// Represents the line number where the cursor is currently located.
/// </summary>
public int LineNumber { get; set; }
/// <summary>
/// Represents the starting index of the selection.
/// </summary>
public int SelectionStartIndex { get; set; }
/// <summary>
/// Represents the length of the selection.
/// </summary>
public int SelectionLength { get; set; }
}
}

View File

@ -1,71 +0,0 @@
using System.Drawing;
using TextControlBoxNS.Extensions;
namespace TextControlBoxNS
{
/// <summary>
/// Represents a syntax highlight definition for a specific pattern in the text.
/// </summary>
public class SyntaxHighlights
{
private readonly ColorConverter ColorConverter = new ColorConverter();
/// <summary>
/// Initializes a new instance of the SyntaxHighlights class with the specified pattern, colors, and font styles.
/// </summary>
/// <param name="pattern">The pattern to be highlighted in the text content.</param>
/// <param name="colorLight">The color representation for the pattern in the light theme (e.g., "#RRGGBB" format).</param>
/// <param name="colorDark">The color representation for the pattern in the dark theme (e.g., "#RRGGBB" format).</param>
/// <param name="bold">true if the pattern should be displayed in bold font; otherwise, false.</param>
/// <param name="italic">true if the pattern should be displayed in italic font; otherwise, false.</param>
/// <param name="underlined">true if the pattern should be displayed with an underline; otherwise, false.</param>
public SyntaxHighlights(string pattern, string colorLight, string colorDark, bool bold = false, bool italic = false, bool underlined = false)
{
this.Pattern = pattern;
this.ColorDark = colorDark;
this.ColorLight = colorLight;
if (underlined || italic || bold)
this.CodeStyle = new CodeFontStyle(underlined, italic, bold);
}
/// <summary>
/// Gets or sets the font style for the pattern.
/// </summary>
public CodeFontStyle CodeStyle { get; set; } = null;
/// <summary>
/// Gets or sets the pattern to be highlighted in the text content.
/// </summary>
public string Pattern { get; set; }
/// <summary>
/// Gets the color representation for the pattern in the dark theme.
/// </summary>
public Windows.UI.Color ColorDark_Clr { get; private set; }
/// <summary>
/// Gets the color representation for the pattern in the light theme.
/// </summary>
public Windows.UI.Color ColorLight_Clr { get; private set; }
/// <summary>
/// Sets the color representation for the pattern in the dark theme.
/// </summary>
/// <param name="value">The color representation for the pattern in the dark theme (e.g., "#RRGGBB" format).</param>
public string ColorDark
{
set => ColorDark_Clr = ((Color)ColorConverter.ConvertFromString(value)).ToMediaColor();
}
/// <summary>
/// Sets the color representation for the pattern in the light theme.
/// </summary>
/// <param name="value">The color representation for the pattern in the light theme (e.g., "#RRGGBB" format).</param>
public string ColorLight
{
set => ColorLight_Clr = ((Color)ColorConverter.ConvertFromString(value)).ToMediaColor();
}
}
}

View File

@ -1,89 +0,0 @@
using Microsoft.UI.Xaml.Media;
using Windows.UI;
namespace TextControlBoxNS
{
/// <summary>
/// Represents the design settings for the textbox.
/// </summary>
public class TextControlBoxDesign
{
/// <summary>
/// Create an instance of the TextControlBoxDesign from a given design
/// </summary>
/// <param name="design">The design to create a new instance from</param>
public TextControlBoxDesign(TextControlBoxDesign design)
{
this.Background = design.Background;
this.TextColor = design.TextColor;
this.SelectionColor = design.SelectionColor;
this.CursorColor = design.CursorColor;
this.LineHighlighterColor = design.LineHighlighterColor;
this.LineNumberColor = design.LineNumberColor;
this.LineNumberBackground = design.LineNumberBackground;
}
/// <summary>
/// Create a new instance of the TextControlBoxDesign class
/// </summary>
/// <param name="background">The background color of the textbox</param>
/// <param name="textColor">The color of the text</param>
/// <param name="selectionColor">The color of the selection</param>
/// <param name="cursorColor">The color of the cursor</param>
/// <param name="lineHighlighterColor">The color of the linehighlighter</param>
/// <param name="lineNumberColor">The color of the linenumber</param>
/// <param name="lineNumberBackground">The background color of the linenumbers</param>
/// <param name="searchHighlightColor">The color of the search highlights</param>
public TextControlBoxDesign(Brush background, Color textColor, Color selectionColor, Color cursorColor, Color lineHighlighterColor, Color lineNumberColor, Color lineNumberBackground, Color searchHighlightColor)
{
this.Background = background;
this.TextColor = textColor;
this.SelectionColor = selectionColor;
this.CursorColor = cursorColor;
this.LineHighlighterColor = lineHighlighterColor;
this.LineNumberColor = lineNumberColor;
this.LineNumberBackground = lineNumberBackground;
this.SearchHighlightColor = searchHighlightColor;
}
/// <summary>
/// Gets or sets the background color of the textbox.
/// </summary>
public Brush Background { get; set; }
/// <summary>
/// Gets or sets the text color of the textbox.
/// </summary>
public Color TextColor { get; set; }
/// <summary>
/// Gets or sets the color of the selected text in the textbox.
/// </summary>
public Color SelectionColor { get; set; }
/// <summary>
/// Gets or sets the color of the cursor in the textbox.
/// </summary>
public Color CursorColor { get; set; }
/// <summary>
/// Gets or sets the color of the line highlighter in the textbox.
/// </summary>
public Color LineHighlighterColor { get; set; }
/// <summary>
/// Gets or sets the color of the line numbers in the textbox.
/// </summary>
public Color LineNumberColor { get; set; }
/// <summary>
/// Gets or sets the background color of the line numbers in the textbox.
/// </summary>
public Color LineNumberBackground { get; set; }
/// <summary>
/// Gets or sets the color used to highlight search results in the textbox.
/// </summary>
public Color SearchHighlightColor { get; set; }
}
}

View File

@ -1,52 +0,0 @@
namespace TextControlBoxNS.Text
{
internal class TextSelection
{
public TextSelection()
{
Index = 0;
Length = 0;
StartPosition = null;
EndPosition = null;
}
public TextSelection(int index = 0, int length = 0, CursorPosition startPosition = null, CursorPosition endPosition = null)
{
Index = index;
Length = length;
StartPosition = startPosition;
EndPosition = endPosition;
}
public TextSelection(CursorPosition startPosition = null, CursorPosition endPosition = null)
{
StartPosition = startPosition;
EndPosition = endPosition;
}
public TextSelection(TextSelection textSelection)
{
StartPosition = new CursorPosition(textSelection.StartPosition);
EndPosition = new CursorPosition(textSelection.EndPosition);
Index = textSelection.Index;
Length = textSelection.Length;
}
public int Index { get; set; }
public int Length { get; set; }
public CursorPosition StartPosition { get; set; }
public CursorPosition EndPosition { get; set; }
public bool IsLineInSelection(int line)
{
if (this.StartPosition != null && this.EndPosition != null)
{
if (this.StartPosition.LineNumber > this.EndPosition.LineNumber)
return this.StartPosition.LineNumber < line && this.EndPosition.LineNumber > line;
else if (this.StartPosition.LineNumber == this.EndPosition.LineNumber)
return this.StartPosition.LineNumber != line;
else
return this.StartPosition.LineNumber > line && this.EndPosition.LineNumber < line;
}
return false;
}
}
}

View File

@ -1,29 +0,0 @@
namespace TextControlBoxNS
{
/// <summary>
/// Represents the position and length of a text selection in the textbox.
/// </summary>
public class TextSelectionPosition
{
/// <summary>
/// Initializes a new instance of the TextSelectionPosition class with the specified index and length.
/// </summary>
/// <param name="index">The start index of the text selection.</param>
/// <param name="length">The length of the text selection.</param>
public TextSelectionPosition(int index = 0, int length = 0)
{
this.Index = index;
this.Length = length;
}
/// <summary>
/// Gets or sets the start index of the text selection.
/// </summary>
public int Index { get; set; }
/// <summary>
/// Gets or sets the length of the text selection.
/// </summary>
public int Length { get; set; }
}
}

View File

@ -1,14 +0,0 @@
using TextControlBoxNS.Text;
namespace TextControlBoxNS.Models
{
internal struct UndoRedoItem
{
public int StartLine { get; set; }
public string UndoText { get; set; }
public string RedoText { get; set; }
public int UndoCount { get; set; }
public int RedoCount { get; set; }
public TextSelection Selection { get; set; }
}
}

View File

@ -1,52 +0,0 @@
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using System.Numerics;
using Windows.Foundation;
namespace TextControlBoxNS.Renderer
{
internal class CursorRenderer
{
public static int GetCursorLineFromPoint(Point point, float singleLineHeight, int numberOfRenderedLines, int numberOfStartLine)
{
//Calculate the relative linenumber, where the pointer was pressed at
int linenumber = (int)(point.Y / singleLineHeight);
linenumber += numberOfStartLine;
return Math.Clamp(linenumber, 0, numberOfStartLine + numberOfRenderedLines - 1);
}
public static int GetCharacterPositionFromPoint(string currentLine, CanvasTextLayout textLayout, Point cursorPosition, float marginLeft)
{
if (currentLine == null || textLayout == null)
return 0;
textLayout.HitTest(
(float)cursorPosition.X - marginLeft, 0,
out var textLayoutRegion);
return textLayoutRegion.CharacterIndex;
}
//Return the position in pixels of the cursor in the current line
public static float GetCursorPositionInLine(CanvasTextLayout currentLineTextLayout, CursorPosition cursorPosition, float xOffset)
{
if (currentLineTextLayout == null)
return 0;
return currentLineTextLayout.GetCaretPosition(cursorPosition.CharacterPosition < 0 ? 0 : cursorPosition.CharacterPosition, false).X + xOffset;
}
//Return the cursor Width
public static void RenderCursor(CanvasTextLayout textLayout, int characterPosition, float xOffset, float y, float fontSize, CursorSize customSize, CanvasDrawEventArgs args, CanvasSolidColorBrush cursorColorBrush)
{
if (textLayout == null)
return;
Vector2 vector = textLayout.GetCaretPosition(characterPosition < 0 ? 0 : characterPosition, false);
if (customSize == null)
args.DrawingSession.FillRectangle(vector.X + xOffset, y, 1, fontSize, cursorColorBrush);
else
args.DrawingSession.FillRectangle(vector.X + xOffset + customSize.OffsetX, y + customSize.OffsetY, (float)customSize.Width, (float)customSize.Height, cursorColorBrush);
}
}
}

View File

@ -1,17 +0,0 @@
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
namespace TextControlBoxNS.Renderer
{
internal class LineHighlighterRenderer
{
public static void Render(float canvasWidth, CanvasTextLayout textLayout, float y, float fontSize, CanvasDrawEventArgs args, CanvasSolidColorBrush backgroundBrush)
{
if (textLayout == null)
return;
args.DrawingSession.FillRectangle(0, y, canvasWidth, fontSize, backgroundBrush);
}
}
}

View File

@ -1,47 +0,0 @@
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using System.Text.RegularExpressions;
using TextControlBoxNS.Helper;
using Windows.UI;
namespace TextControlBoxNS.Renderer
{
internal class SearchHighlightsRenderer
{
public static void RenderHighlights(
CanvasDrawEventArgs args,
CanvasTextLayout drawnTextLayout,
string renderedText,
int[] possibleLines,
string searchRegex,
float scrollOffsetX,
float offsetTop,
Color searchHighlightColor)
{
if (searchRegex == null || possibleLines == null || possibleLines.Length == 0)
return;
MatchCollection matches;
try
{
matches = Regex.Matches(renderedText, searchRegex);
}
catch (ArgumentException)
{
return;
}
for (int j = 0; j < matches.Count; j++)
{
var match = matches[j];
var layoutRegion = drawnTextLayout.GetCharacterRegions(match.Index, match.Length);
if (layoutRegion.Length > 0)
{
args.DrawingSession.FillRectangle(Utils.CreateRect(layoutRegion[0].LayoutBounds, scrollOffsetX, offsetTop), searchHighlightColor);
}
}
return;
}
}
}

View File

@ -1,209 +0,0 @@
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Linq;
using TextControlBoxNS.Helper;
using TextControlBoxNS.Text;
using Windows.Foundation;
using Windows.UI;
namespace TextControlBoxNS.Renderer
{
internal class SelectionRenderer
{
public bool HasSelection = false;
public bool IsSelecting = false;
public bool IsSelectingOverLinenumbers = false;
public CursorPosition SelectionStartPosition = null;
public CursorPosition SelectionEndPosition = null;
public int SelectionLength = 0;
public int SelectionStart = 0;
//Draw the actual selection and return the cursorposition. Return -1 if no selection was drawn
public TextSelection DrawSelection(
CanvasTextLayout textLayout,
IEnumerable<string> renderedLines,
CanvasDrawEventArgs args,
float marginLeft,
float marginTop,
int unrenderedLinesToRenderStart,
int numberOfRenderedLines,
float fontSize,
Color selectionColor
)
{
if (HasSelection && SelectionEndPosition != null && SelectionStartPosition != null)
{
int selStartIndex = 0;
int selEndIndex = 0;
int characterPosStart = SelectionStartPosition.CharacterPosition;
int characterPosEnd = SelectionEndPosition.CharacterPosition;
//Render the selection on position 0 if the user scrolled the start away
if (SelectionEndPosition.LineNumber < SelectionStartPosition.LineNumber)
{
if (SelectionEndPosition.LineNumber < unrenderedLinesToRenderStart)
characterPosEnd = 0;
if (SelectionStartPosition.LineNumber < unrenderedLinesToRenderStart + 1)
characterPosStart = 0;
}
else if (SelectionEndPosition.LineNumber == SelectionStartPosition.LineNumber)
{
if (SelectionStartPosition.LineNumber < unrenderedLinesToRenderStart)
characterPosStart = 0;
if (SelectionEndPosition.LineNumber < unrenderedLinesToRenderStart)
characterPosEnd = 0;
}
else
{
if (SelectionStartPosition.LineNumber < unrenderedLinesToRenderStart)
characterPosStart = 0;
if (SelectionEndPosition.LineNumber < unrenderedLinesToRenderStart + 1)
characterPosEnd = 0;
}
if (SelectionStartPosition.LineNumber == SelectionEndPosition.LineNumber)
{
int lenghtToLine = 0;
for (int i = 0; i < SelectionStartPosition.LineNumber - unrenderedLinesToRenderStart; i++)
{
if (i < numberOfRenderedLines)
{
lenghtToLine += renderedLines.ElementAt(i).Length + 1;
}
}
selStartIndex = characterPosStart + lenghtToLine;
selEndIndex = characterPosEnd + lenghtToLine;
}
else
{
for (int i = 0; i < SelectionStartPosition.LineNumber - unrenderedLinesToRenderStart; i++)
{
if (i >= numberOfRenderedLines) //Out of range of the List (do nothing)
break;
selStartIndex += renderedLines.ElementAt(i).Length + 1;
}
selStartIndex += characterPosStart;
for (int i = 0; i < SelectionEndPosition.LineNumber - unrenderedLinesToRenderStart; i++)
{
if (i >= numberOfRenderedLines) //Out of range of the List (do nothing)
break;
selEndIndex += renderedLines.ElementAt(i).Length + 1;
}
selEndIndex += characterPosEnd;
}
SelectionStart = Math.Min(selStartIndex, selEndIndex);
if (SelectionStart < 0)
SelectionStart = 0;
if (SelectionLength < 0)
SelectionLength = 0;
if (selEndIndex > selStartIndex)
SelectionLength = selEndIndex - selStartIndex;
else
SelectionLength = selStartIndex - selEndIndex;
CanvasTextLayoutRegion[] descriptions = textLayout.GetCharacterRegions(SelectionStart, SelectionLength);
for (int i = 0; i < descriptions.Length; i++)
{
//Change the width if selection in an emty line or starts at a line end
if (descriptions[i].LayoutBounds.Width == 0 && descriptions.Length > 1)
{
var bounds = descriptions[i].LayoutBounds;
descriptions[i].LayoutBounds = new Rect { Width = fontSize / 4, Height = bounds.Height, X = bounds.X, Y = bounds.Y };
}
args.DrawingSession.FillRectangle(Utils.CreateRect(descriptions[i].LayoutBounds, marginLeft, marginTop), selectionColor);
}
return new TextSelection(SelectionStart, SelectionLength, new CursorPosition(SelectionStartPosition), new CursorPosition(SelectionEndPosition));
}
return null;
}
//returns whether the pointer is over a selection
public bool PointerIsOverSelection(Point pointerPosition, TextSelection selection, CanvasTextLayout textLayout)
{
if (textLayout == null || selection == null)
return false;
CanvasTextLayoutRegion[] regions = textLayout.GetCharacterRegions(selection.Index, selection.Length);
for (int i = 0; i < regions.Length; i++)
{
if (regions[i].LayoutBounds.Contains(pointerPosition))
return true;
}
return false;
}
public bool CursorIsInSelection(CursorPosition cursorPosition, TextSelection textSelection)
{
if (textSelection == null)
return false;
textSelection = Selection.OrderTextSelection(textSelection);
//Cursorposition is smaller than the start of selection
if (textSelection.StartPosition.LineNumber > cursorPosition.LineNumber)
return false;
//Selectionend is smaller than Cursorposition -> not in selection
if (textSelection.EndPosition.LineNumber < cursorPosition.LineNumber)
return false;
//Selection-start line equals Cursor line:
if (cursorPosition.LineNumber == textSelection.StartPosition.LineNumber)
return cursorPosition.CharacterPosition > textSelection.StartPosition.CharacterPosition;
//Selection-end line equals Cursor line
else if (cursorPosition.LineNumber == textSelection.EndPosition.LineNumber)
return cursorPosition.CharacterPosition < textSelection.EndPosition.CharacterPosition;
return true;
}
//Clear the selection
public void ClearSelection()
{
HasSelection = false;
IsSelecting = false;
SelectionEndPosition = null;
SelectionStartPosition = null;
}
public void SetSelection(TextSelection selection)
{
if (selection == null)
return;
SetSelection(selection.StartPosition, selection.EndPosition);
}
public void SetSelection(CursorPosition startPosition, CursorPosition endPosition)
{
IsSelecting = true;
SelectionStartPosition = startPosition;
SelectionEndPosition = endPosition;
IsSelecting = false;
HasSelection = true;
}
public void SetSelectionStart(CursorPosition startPosition)
{
IsSelecting = true;
SelectionStartPosition = startPosition;
IsSelecting = false;
HasSelection = true;
}
public void SetSelectionEnd(CursorPosition endPosition)
{
IsSelecting = true;
SelectionEndPosition = endPosition;
IsSelecting = false;
HasSelection = true;
}
}
}

View File

@ -1,73 +0,0 @@
using Microsoft.Graphics.Canvas.Text;
using Microsoft.UI.Xaml;
using Newtonsoft.Json;
using System;
using System.Text.RegularExpressions;
using Windows.UI.Text;
using Windows.UI.Xaml;
namespace TextControlBoxNS.Renderer
{
internal class SyntaxHighlightingRenderer
{
public static FontWeight BoldFont = new FontWeight { Weight = 600 };
public static FontStyle ItalicFont = FontStyle.Italic;
public static void UpdateSyntaxHighlighting(CanvasTextLayout drawnTextLayout, ApplicationTheme theme, CodeLanguage codeLanguage, bool syntaxHighlighting, string renderedText)
{
if (codeLanguage == null || !syntaxHighlighting)
return;
var highlights = codeLanguage.Highlights;
for (int i = 0; i < highlights.Length; i++)
{
var matches = Regex.Matches(renderedText, highlights[i].Pattern, RegexOptions.Compiled);
var highlight = highlights[i];
var color = theme == ApplicationTheme.Light ? highlight.ColorLight_Clr : highlight.ColorDark_Clr;
for (int j = 0; j < matches.Count; j++)
{
var match = matches[j];
int index = match.Index;
int length = match.Length;
drawnTextLayout.SetColor(index, length, color);
if (highlight.CodeStyle != null)
{
if (highlight.CodeStyle.Italic)
drawnTextLayout.SetFontStyle(index, length, ItalicFont);
if (highlight.CodeStyle.Bold)
drawnTextLayout.SetFontWeight(index, length, BoldFont);
if (highlight.CodeStyle.Underlined)
drawnTextLayout.SetUnderline(index, length, true);
}
}
}
}
public static JsonLoadResult GetCodeLanguageFromJson(string json)
{
try
{
var jsonCodeLanguage = JsonConvert.DeserializeObject<JsonCodeLanguage>(json);
//Apply the filter as an array
var codelanguage = new CodeLanguage
{
Author = jsonCodeLanguage.Author,
Description = jsonCodeLanguage.Description,
Highlights = jsonCodeLanguage.Highlights,
Name = jsonCodeLanguage.Name,
Filter = jsonCodeLanguage.Filter.Split("|", StringSplitOptions.RemoveEmptyEntries),
};
return new JsonLoadResult(true, codelanguage);
}
catch (JsonReaderException)
{
return new JsonLoadResult(false, null);
}
catch (JsonSerializationException)
{
return new JsonLoadResult(false, null);
}
}
}
}

View File

@ -1,38 +0,0 @@
using System.Linq;
namespace TextControlBoxNS.Text
{
internal class AutoPairing
{
public static (string text, int length) AutoPair(TextControlBox textbox, string inputtext)
{
if (!textbox.DoAutoPairing || inputtext.Length != 1 || textbox.CodeLanguage == null || textbox.CodeLanguage.AutoPairingPair == null)
return (inputtext, inputtext.Length);
var res = textbox.CodeLanguage.AutoPairingPair.Where(x => x.Matches(inputtext));
if (res.Count() == 0)
return (inputtext, inputtext.Length);
if (res.ElementAt(0) is AutoPairingPair pair)
return (inputtext + pair.Pair, inputtext.Length);
return (inputtext, inputtext.Length);
}
public static string AutoPairSelection(TextControlBox textbox, string inputtext)
{
if (!textbox.DoAutoPairing || inputtext.Length != 1 || textbox.CodeLanguage == null || textbox.CodeLanguage.AutoPairingPair == null)
return inputtext;
var res = textbox.CodeLanguage.AutoPairingPair.Where(x => x.Value.Equals(inputtext));
if (res.Count() == 0)
return inputtext;
if (res.ElementAt(0) is AutoPairingPair pair)
{
textbox.SurroundSelectionWith(inputtext, pair.Pair);
return null;
}
return inputtext;
}
}
}

View File

@ -1,170 +0,0 @@
using Collections.Pooled;
using System;
using TextControlBoxNS.Extensions;
using TextControlBoxNS.Helper;
namespace TextControlBoxNS.Text
{
internal class Cursor
{
private static int CheckIndex(string str, int index) => Math.Clamp(index, 0, str.Length - 1);
public static int CursorPositionToIndex(PooledList<string> totalLines, CursorPosition cursorPosition)
{
int cursorIndex = cursorPosition.CharacterPosition;
int lineNumber = cursorPosition.LineNumber < totalLines.Count ? cursorIndex : totalLines.Count - 1;
for (int i = 0; i < lineNumber; i++)
{
cursorIndex += totalLines.GetLineLength(i) + 1;
}
return cursorIndex;
}
public static bool Equals(CursorPosition curPos1, CursorPosition curPos2)
{
if (curPos1 == null || curPos2 == null)
return false;
if (curPos1.LineNumber == curPos2.LineNumber)
return curPos1.CharacterPosition == curPos2.CharacterPosition;
return false;
}
//Calculate the number of characters from the cursorposition to the next character or digit to the left and to the right
public static int CalculateStepsToMoveLeft2(string currentLine, int cursorCharPosition)
{
if (currentLine.Length == 0)
return 0;
int stepsToMove = 0;
for (int i = cursorCharPosition - 1; i >= 0; i--)
{
char currentCharacter = currentLine[CheckIndex(currentLine, i)];
if (char.IsLetterOrDigit(currentCharacter) || currentCharacter == '_')
stepsToMove++;
else if (i == cursorCharPosition - 1 && char.IsWhiteSpace(currentCharacter))
return 0;
else
break;
}
return stepsToMove;
}
public static int CalculateStepsToMoveRight2(string currentLine, int cursorCharPosition)
{
if (currentLine.Length == 0)
return 0;
int stepsToMove = 0;
for (int i = cursorCharPosition; i < currentLine.Length; i++)
{
char currentCharacter = currentLine[CheckIndex(currentLine, i)];
if (char.IsLetterOrDigit(currentCharacter) || currentCharacter == '_')
stepsToMove++;
else if (i == cursorCharPosition && char.IsWhiteSpace(currentCharacter))
return 0;
else
break;
}
return stepsToMove;
}
//Calculates how many characters the cursor needs to move if control is pressed
//Returns 1 when control is not pressed
public static int CalculateStepsToMoveLeft(string currentLine, int cursorCharPosition)
{
if (!Utils.IsKeyPressed(Windows.System.VirtualKey.Control))
return 1;
int stepsToMove = 0;
for (int i = cursorCharPosition - 1; i >= 0; i--)
{
char CurrentCharacter = currentLine[CheckIndex(currentLine, i)];
if (char.IsLetterOrDigit(CurrentCharacter) || CurrentCharacter == '_')
stepsToMove++;
else if (i == cursorCharPosition - 1 && char.IsWhiteSpace(CurrentCharacter))
stepsToMove++;
else
break;
}
//If it ignores the ControlKey return the real value of stepsToMove otherwise
//return 1 if stepsToMove is 0
return stepsToMove == 0 ? 1 : stepsToMove;
}
public static int CalculateStepsToMoveRight(string currentLine, int cursorCharPosition)
{
if (!Utils.IsKeyPressed(Windows.System.VirtualKey.Control))
return 1;
int stepsToMove = 0;
for (int i = cursorCharPosition; i < currentLine.Length; i++)
{
char CurrentCharacter = currentLine[CheckIndex(currentLine, i)];
if (char.IsLetterOrDigit(CurrentCharacter) || CurrentCharacter == '_')
stepsToMove++;
else if (i == cursorCharPosition && char.IsWhiteSpace(CurrentCharacter))
stepsToMove++;
else
break;
}
//If it ignores the ControlKey return the real value of stepsToMove otherwise
//return 1 if stepsToMove is 0
return stepsToMove == 0 ? 1 : stepsToMove;
}
//Move cursor:
public static void MoveLeft(CursorPosition currentCursorPosition, PooledList<string> totalLines, string currentLine)
{
if (currentCursorPosition.LineNumber < 0)
return;
int currentLineLength = totalLines.GetLineLength(currentCursorPosition.LineNumber);
if (currentCursorPosition.CharacterPosition == 0 && currentCursorPosition.LineNumber > 0)
{
currentCursorPosition.CharacterPosition = totalLines.GetLineLength(currentCursorPosition.LineNumber - 1);
currentCursorPosition.LineNumber -= 1;
}
else if (currentCursorPosition.CharacterPosition > currentLineLength)
currentCursorPosition.CharacterPosition = currentLineLength - 1;
else if (currentCursorPosition.CharacterPosition > 0)
currentCursorPosition.CharacterPosition -= CalculateStepsToMoveLeft(currentLine, currentCursorPosition.CharacterPosition);
}
public static void MoveRight(CursorPosition currentCursorPosition, PooledList<string> totalLines, string currentLine)
{
int lineLength = totalLines.GetLineLength(currentCursorPosition.LineNumber);
if (currentCursorPosition.LineNumber > totalLines.Count - 1)
return;
if (currentCursorPosition.CharacterPosition == lineLength && currentCursorPosition.LineNumber < totalLines.Count - 1)
{
currentCursorPosition.CharacterPosition = 0;
currentCursorPosition.LineNumber += 1;
}
else if (currentCursorPosition.CharacterPosition < lineLength)
currentCursorPosition.CharacterPosition += CalculateStepsToMoveRight(currentLine, currentCursorPosition.CharacterPosition);
if (currentCursorPosition.CharacterPosition > lineLength)
currentCursorPosition.CharacterPosition = lineLength;
}
public static CursorPosition MoveDown(CursorPosition currentCursorPosition, int totalLinesLength)
{
CursorPosition returnValue = new CursorPosition(currentCursorPosition);
if (currentCursorPosition.LineNumber < totalLinesLength - 1)
returnValue = CursorPosition.ChangeLineNumber(currentCursorPosition, currentCursorPosition.LineNumber + 1);
return returnValue;
}
public static CursorPosition MoveUp(CursorPosition currentCursorPosition)
{
CursorPosition returnValue = new CursorPosition(currentCursorPosition);
if (currentCursorPosition.LineNumber > 0)
returnValue = CursorPosition.ChangeLineNumber(returnValue, currentCursorPosition.LineNumber - 1);
return returnValue;
}
public static void MoveToLineEnd(CursorPosition cursorPosition, string currentLine)
{
cursorPosition.CharacterPosition = currentLine.Length;
}
public static void MoveToLineStart(CursorPosition cursorPosition)
{
cursorPosition.CharacterPosition = 0;
}
}
}

View File

@ -1,31 +0,0 @@
using System;
using System.Text.RegularExpressions;
namespace TextControlBoxNS.Text
{
internal class LineEndings
{
public static string LineEndingToString(LineEnding lineEnding)
{
return
lineEnding == LineEnding.LF ? "\n" :
lineEnding == LineEnding.CRLF ? "\r\n" :
"\r";
}
public static LineEnding FindLineEnding(string text)
{
if (text.IndexOf("\r\n", StringComparison.Ordinal) > -1)
return LineEnding.CRLF;
else if (text.IndexOf("\n", StringComparison.Ordinal) > -1)
return LineEnding.LF;
else if (text.IndexOf("\r", StringComparison.Ordinal) > -1)
return LineEnding.CR;
return LineEnding.CRLF;
}
public static string CleanLineEndings(string text, LineEnding lineEnding)
{
return Regex.Replace(text, "(\r\n|\r|\n)", LineEndingToString(lineEnding));
}
}
}

View File

@ -1,35 +0,0 @@
using Collections.Pooled;
namespace TextControlBoxNS.Text
{
internal class MoveLine
{
public static void Move(PooledList<string> totalLines, TextSelection selection, CursorPosition cursorposition, UndoRedo undoredo, string newLineCharacter, LineMoveDirection direction)
{
if (selection != null)
return;
//move down:
if (direction == LineMoveDirection.Down)
{
if (cursorposition.LineNumber >= totalLines.Count - 1)
return;
undoredo.RecordUndoAction(() =>
{
Selection.MoveLinesDown(totalLines, selection, cursorposition);
}, totalLines, cursorposition.LineNumber, 2, 2, newLineCharacter, cursorposition);
return;
}
//move up:
if (cursorposition.LineNumber <= 0)
return;
undoredo.RecordUndoAction(() =>
{
Selection.MoveLinesUp(totalLines, selection, cursorposition);
}, totalLines, cursorposition.LineNumber - 1, 2, 2, newLineCharacter, cursorposition);
}
}
}

View File

@ -1,527 +0,0 @@
using Collections.Pooled;
using System;
using System.Linq;
using System.Text;
using TextControlBoxNS.Extensions;
using TextControlBoxNS.Helper;
using TextControlBoxNS.Renderer;
namespace TextControlBoxNS.Text
{
internal class Selection
{
public static bool Equals(TextSelection sel1, TextSelection sel2)
{
if (sel1 == null || sel2 == null)
return false;
return Cursor.Equals(sel1.StartPosition, sel2.StartPosition) &&
Cursor.Equals(sel1.EndPosition, sel2.EndPosition);
}
//Order the selection that StartPosition is always smaller than EndPosition
public static TextSelection OrderTextSelection(TextSelection selection)
{
if (selection == null)
return selection;
int startLine = Math.Min(selection.StartPosition.LineNumber, selection.EndPosition.LineNumber);
int endLine = Math.Max(selection.StartPosition.LineNumber, selection.EndPosition.LineNumber);
int startPosition;
int endPosition;
if (startLine == endLine)
{
startPosition = Math.Min(selection.StartPosition.CharacterPosition, selection.EndPosition.CharacterPosition);
endPosition = Math.Max(selection.StartPosition.CharacterPosition, selection.EndPosition.CharacterPosition);
}
else
{
if (selection.StartPosition.LineNumber < selection.EndPosition.LineNumber)
{
endPosition = selection.EndPosition.CharacterPosition;
startPosition = selection.StartPosition.CharacterPosition;
}
else
{
endPosition = selection.StartPosition.CharacterPosition;
startPosition = selection.EndPosition.CharacterPosition;
}
}
return new TextSelection(selection.Index, selection.Length, new CursorPosition(startPosition, startLine), new CursorPosition(endPosition, endLine));
}
public static bool WholeTextSelected(TextSelection selection, PooledList<string> totalLines)
{
if (selection == null)
return false;
var sel = OrderTextSelection(selection);
return Utils.CursorPositionsAreEqual(sel.StartPosition, new CursorPosition(0, 0)) &&
Utils.CursorPositionsAreEqual(sel.EndPosition, new CursorPosition(totalLines.GetLineLength(-1), totalLines.Count - 1));
}
//returns whether the selection starts at character zero and ends
public static bool WholeLinesAreSelected(TextSelection selection, PooledList<string> totalLines)
{
if (selection == null)
return false;
var sel = OrderTextSelection(selection);
return Utils.CursorPositionsAreEqual(sel.StartPosition, new CursorPosition(0, sel.StartPosition.LineNumber)) &&
Utils.CursorPositionsAreEqual(sel.EndPosition, new CursorPosition(totalLines.GetLineText(sel.EndPosition.LineNumber).Length, sel.EndPosition.LineNumber));
}
public static CursorPosition GetMax(CursorPosition pos1, CursorPosition pos2)
{
if (pos1.LineNumber == pos2.LineNumber)
return pos1.CharacterPosition > pos2.CharacterPosition ? pos1 : pos2;
return pos1.LineNumber > pos2.LineNumber ? pos1 : pos2;
}
public static CursorPosition GetMin(CursorPosition pos1, CursorPosition pos2)
{
if (pos1.LineNumber == pos2.LineNumber)
return pos1.CharacterPosition > pos2.CharacterPosition ? pos2 : pos1;
return pos1.LineNumber > pos2.LineNumber ? pos2 : pos1;
}
public static CursorPosition GetMin(TextSelection selection)
{
return GetMin(selection.StartPosition, selection.EndPosition);
}
public static CursorPosition GetMax(TextSelection selection)
{
return GetMax(selection.StartPosition, selection.EndPosition);
}
public static CursorPosition InsertText(TextSelection selection, CursorPosition cursorPosition, PooledList<string> totalLines, string text, string newLineCharacter)
{
if (selection != null)
return Replace(selection, totalLines, text, newLineCharacter);
string curLine = totalLines.GetLineText(cursorPosition.LineNumber);
string[] lines = text.Split(newLineCharacter);
//Singleline
if (lines.Length == 1 && text != string.Empty)
{
text = text.Replace("\r", string.Empty).Replace("\n", string.Empty);
totalLines.SetLineText(-1, totalLines.GetLineText(-1).AddText(text, cursorPosition.CharacterPosition));
cursorPosition.AddToCharacterPos(text.Length);
return cursorPosition;
}
//Multiline:
int curPos = cursorPosition.CharacterPosition;
if (curPos > curLine.Length)
curPos = curLine.Length;
//GEt the text in front of the cursor
string textInFrontOfCursor = curLine.Substring(0, curPos < 0 ? 0 : curPos);
//Get the text behind the cursor
string textBehindCursor = curLine.SafeRemove(0, curPos < 0 ? 0 : curPos);
totalLines.DeleteAt(cursorPosition.LineNumber);
totalLines.InsertOrAddRange(ListHelper.CreateLines(lines, 0, textInFrontOfCursor, textBehindCursor), cursorPosition.LineNumber);
return new CursorPosition(cursorPosition.CharacterPosition + lines.Length > 0 ? lines[lines.Length - 1].Length : 0, cursorPosition.LineNumber + lines.Length - 1);
}
public static CursorPosition Replace(TextSelection selection, PooledList<string> totalLines, string text, string newLineCharacter)
{
//Just delete the text if the string is emty
if (text == "")
return Remove(selection, totalLines);
selection = OrderTextSelection(selection);
int startLine = selection.StartPosition.LineNumber;
int endLine = selection.EndPosition.LineNumber;
int startPosition = selection.StartPosition.CharacterPosition;
int endPosition = selection.EndPosition.CharacterPosition;
string[] lines = text.Split(newLineCharacter);
string start_Line = totalLines.GetLineText(startLine);
//Selection is singleline and text to paste is also singleline
if (startLine == endLine && lines.Length == 1)
{
start_Line =
(startPosition == 0 && endPosition == totalLines.GetLineLength(endLine)) ?
"" :
start_Line.SafeRemove(startPosition, endPosition - startPosition
);
totalLines.SetLineText(startLine, start_Line.AddText(text, startPosition));
return new CursorPosition(startPosition + text.Length, selection.StartPosition.LineNumber);
}
else if (startLine == endLine && lines.Length > 1 && (startPosition != 0 && endPosition != start_Line.Length))
{
string textTo = start_Line == "" ? "" : startPosition >= start_Line.Length ? start_Line : start_Line.Safe_Substring(0, startPosition);
string textFrom = start_Line == "" ? "" : endPosition >= start_Line.Length ? start_Line : start_Line.Safe_Substring(endPosition);
totalLines.SetLineText(startLine, (textTo + lines[0]));
totalLines.InsertOrAddRange(ListHelper.CreateLines(lines, 1, "", textFrom), startLine + 1);
return new CursorPosition(endPosition + text.Length, startLine + lines.Length - 1);
}
else if (WholeTextSelected(selection, totalLines))
{
if (lines.Length < totalLines.Count)
{
ListHelper.Clear(totalLines);
totalLines.InsertOrAddRange(lines, 0);
}
else
ReplaceLines(totalLines, 0, totalLines.Count, lines);
return new CursorPosition(totalLines.GetLineLength(-1), totalLines.Count - 1);
}
else
{
string end_Line = totalLines.GetLineText(endLine);
//All lines are selected from start to finish
if (startPosition == 0 && endPosition == end_Line.Length)
{
totalLines.Safe_RemoveRange(startLine, endLine - startLine + 1);
totalLines.InsertOrAddRange(lines, startLine);
}
//Only the startline is completely selected
else if (startPosition == 0 && endPosition != end_Line.Length)
{
totalLines.SetLineText(endLine, end_Line.Substring(endPosition).AddToStart(lines[lines.Length - 1]));
totalLines.Safe_RemoveRange(startLine, endLine - startLine);
totalLines.InsertOrAddRange(lines.Take(lines.Length - 1), startLine);
}
//Only the endline is completely selected
else if (startPosition != 0 && endPosition == end_Line.Length)
{
totalLines.SetLineText(startLine, start_Line.SafeRemove(startPosition).AddToEnd(lines[0]));
totalLines.Safe_RemoveRange(startLine + 1, endLine - startLine);
totalLines.InsertOrAddRange(lines.Skip(1), startLine + 1);
}
else
{
//Delete the selected parts
start_Line = start_Line.SafeRemove(startPosition);
end_Line = end_Line.Safe_Substring(endPosition);
//Only one line to insert
if (lines.Length == 1)
{
totalLines.SetLineText(startLine, start_Line.AddToEnd(lines[0] + end_Line));
totalLines.Safe_RemoveRange(startLine + 1, endLine - startLine < 0 ? 0 : endLine - startLine);
}
else
{
totalLines.SetLineText(startLine, start_Line.AddToEnd(lines[0]));
totalLines.SetLineText(endLine, end_Line.AddToStart(lines[lines.Length - 1]));
totalLines.Safe_RemoveRange(startLine + 1, endLine - startLine - 1 < 0 ? 0 : endLine - startLine - 1);
if (lines.Length > 2)
totalLines.InsertOrAddRange(lines.GetLines(1, lines.Length - 2), startLine + 1);
}
}
return new CursorPosition(start_Line.Length + end_Line.Length - 1, startLine + lines.Length - 1);
}
}
public static CursorPosition Remove(TextSelection selection, PooledList<string> totalLines)
{
selection = OrderTextSelection(selection);
int startLine = selection.StartPosition.LineNumber;
int endLine = selection.EndPosition.LineNumber;
int startPosition = selection.StartPosition.CharacterPosition;
int endPosition = selection.EndPosition.CharacterPosition;
string start_Line = totalLines.GetLineText(startLine);
string end_Line = totalLines.GetLineText(endLine);
if (startLine == endLine)
{
totalLines.SetLineText(startLine,
(startPosition == 0 && endPosition == end_Line.Length ?
"" :
start_Line.SafeRemove(startPosition, endPosition - startPosition))
);
}
else if (WholeTextSelected(selection, totalLines))
{
ListHelper.Clear(totalLines, true);
return new CursorPosition(0, totalLines.Count - 1);
}
else
{
//Whole lines are selected from start to finish
if (startPosition == 0 && endPosition == end_Line.Length)
{
totalLines.Safe_RemoveRange(startLine, endLine - startLine + 1);
}
//Only the startline is completely selected
else if (startPosition == 0 && endPosition != end_Line.Length)
{
totalLines.SetLineText(endLine, end_Line.Safe_Substring(endPosition));
totalLines.Safe_RemoveRange(startLine, endLine - startLine);
}
//Only the endline is completely selected
else if (startPosition != 0 && endPosition == end_Line.Length)
{
totalLines.SetLineText(startLine, start_Line.SafeRemove(startPosition));
totalLines.Safe_RemoveRange(startLine + 1, endLine - startLine);
}
//Both startline and endline are not completely selected
else
{
totalLines.SetLineText(startLine, start_Line.SafeRemove(startPosition) + end_Line.Safe_Substring(endPosition));
totalLines.Safe_RemoveRange(startLine + 1, endLine - startLine);
}
}
if (totalLines.Count == 0)
totalLines.AddLine();
return new CursorPosition(startPosition, startLine);
}
public static TextSelectionPosition GetIndexOfSelection(PooledList<string> totalLines, TextSelection selection)
{
var sel = OrderTextSelection(selection);
int startIndex = Cursor.CursorPositionToIndex(totalLines, sel.StartPosition);
int endIndex = Cursor.CursorPositionToIndex(totalLines, sel.EndPosition);
if (endIndex > startIndex)
return new TextSelectionPosition(Math.Min(startIndex, endIndex), endIndex - startIndex);
else
return new TextSelectionPosition(Math.Min(startIndex, endIndex), startIndex - endIndex);
}
public static TextSelection GetSelectionFromPosition(PooledList<string> totalLines, int startPosition, int length, int numberOfCharacters)
{
TextSelection returnValue = new TextSelection();
if (startPosition + length > numberOfCharacters)
{
if (startPosition > numberOfCharacters)
{
startPosition = numberOfCharacters;
length = 0;
}
else
length = numberOfCharacters - startPosition;
}
void GetIndexInLine(int currentIndex, int currentTotalLength)
{
int position = Math.Abs(currentTotalLength - startPosition);
returnValue.StartPosition =
new CursorPosition(position, currentIndex);
if (length == 0)
returnValue.EndPosition = new CursorPosition(returnValue.StartPosition);
else
{
int lengthCount = 0;
for (int i = currentIndex; i < totalLines.Count; i++)
{
int lineLength = totalLines[i].Length + 1;
if (lengthCount + lineLength > length)
{
returnValue.EndPosition = new CursorPosition(Math.Abs(lengthCount - length) + position, i);
break;
}
lengthCount += lineLength;
}
}
}
//Get the Length
int totalLength = 0;
for (int i = 0; i < totalLines.Count; i++)
{
int lineLength = totalLines[i].Length + 1;
if (totalLength + lineLength > startPosition)
{
GetIndexInLine(i, totalLength);
break;
}
totalLength += lineLength;
}
return returnValue;
}
public static string GetSelectedText(PooledList<string> totalLines, TextSelection textSelection, int currentLineIndex, string newLineCharacter)
{
//return the current line, if no text is selected:
if (textSelection == null)
return totalLines.GetLineText(currentLineIndex) + newLineCharacter;
int startLine = Math.Min(textSelection.StartPosition.LineNumber, textSelection.EndPosition.LineNumber);
int endLine = Math.Max(textSelection.StartPosition.LineNumber, textSelection.EndPosition.LineNumber);
int endIndex = Math.Max(textSelection.StartPosition.CharacterPosition, textSelection.EndPosition.CharacterPosition);
int startIndex = Math.Min(textSelection.StartPosition.CharacterPosition, textSelection.EndPosition.CharacterPosition);
StringBuilder stringBuilder = new StringBuilder();
if (startLine == endLine) //Singleline
{
string line = totalLines.GetLineText(startLine < totalLines.Count ? startLine : totalLines.Count - 1);
if (startIndex == 0 && endIndex != line.Length)
stringBuilder.Append(line.SafeRemove(endIndex));
else if (endIndex == line.Length && startIndex != 0)
stringBuilder.Append(line.Safe_Substring(startIndex));
else if (startIndex == 0 && endIndex == line.Length)
stringBuilder.Append(line);
else stringBuilder.Append(line.SafeRemove(endIndex).Substring(startIndex));
}
else if (WholeTextSelected(textSelection, totalLines))
{
stringBuilder.Append(ListHelper.GetLinesAsString(totalLines, newLineCharacter));
}
else //Multiline
{
//StartLine
stringBuilder.Append(totalLines.GetLineText(startLine).Substring(startIndex) + newLineCharacter);
//Other lines
if (endLine - startLine > 1)
stringBuilder.Append(totalLines.GetLines(startLine + 1, endLine - startLine - 1).GetString(newLineCharacter) + newLineCharacter);
//Endline
string currentLine = totalLines.GetLineText(endLine);
stringBuilder.Append(endIndex >= currentLine.Length ? currentLine : currentLine.SafeRemove(endIndex));
}
return stringBuilder.ToString();
}
/// <summary>
/// Replaces the lines in TotalLines, starting by Start replacing Count number of items, with the string in SplittedText
/// All lines that can be replaced get replaced all lines that are needed additionally get added
/// </summary>
/// <param name="totalLines"></param>
/// <param name="start"></param>
/// <param name="count"></param>
/// <param name="splittedText"></param>
public static void ReplaceLines(PooledList<string> totalLines, int start, int count, string[] splittedText)
{
if (splittedText.Length == 0)
{
totalLines.Safe_RemoveRange(start, count);
return;
}
//Same line-length -> check for any differences in the individual lines
if (count == splittedText.Length)
{
for (int i = 0; i < count; i++)
{
if (!totalLines.GetLineText(i).Equals(splittedText[i], StringComparison.Ordinal))
{
totalLines.SetLineText(start + i, splittedText[i]);
}
}
}
//Delete items from start to count; Insert splittedText at start
else if (count > splittedText.Length)
{
for (int i = 0; i < count; i++)
{
if (i < splittedText.Length)
{
totalLines.SetLineText(start + i, splittedText[i]);
}
else
{
totalLines.Safe_RemoveRange(start + i, count - i);
break;
}
}
}
//Replace all items from start - count with existing (add more if out of range)
else //SplittedText.Length > Count:
{
for (int i = 0; i < splittedText.Length; i++)
{
//replace all possible lines
if (i < count)
{
totalLines.SetLineText(start + i, splittedText[i]);
}
else //Add new lines
{
totalLines.InsertOrAddRange(splittedText.Skip(start + i), start + i);
break;
}
}
}
}
public static bool MoveLinesUp(PooledList<string> totalLines, TextSelection selection, CursorPosition cursorposition)
{
//Move single line
if (selection != null)
return false;
if (cursorposition.LineNumber > 0)
{
totalLines.SwapLines(cursorposition.LineNumber, cursorposition.LineNumber - 1);
cursorposition.LineNumber -= 1;
return true;
}
return false;
}
public static bool MoveLinesDown(PooledList<string> totalLines, TextSelection selection, CursorPosition cursorposition)
{
//Move single line
if (selection != null || selection.StartPosition.LineNumber != selection.EndPosition.LineNumber)
return false;
if (cursorposition.LineNumber < totalLines.Count)
{
totalLines.SwapLines(cursorposition.LineNumber, cursorposition.LineNumber + 1);
cursorposition.LineNumber += 1;
return true;
}
return false;
}
public static void ClearSelectionIfNeeded(TextControlBox textbox, SelectionRenderer selectionrenderer)
{
//If the selection is visible, but is not getting set, clear the selection
if (selectionrenderer.HasSelection && !selectionrenderer.IsSelecting)
{
textbox.ClearSelection();
}
}
public static bool SelectionIsNull(SelectionRenderer selectionrenderer, TextSelection selection)
{
if (selection == null)
return true;
return selectionrenderer.SelectionStartPosition == null || selectionrenderer.SelectionEndPosition == null;
}
public static void SelectSingleWord(CanvasHelper canvashelper, SelectionRenderer selectionrenderer, CursorPosition cursorPosition, string currentLine)
{
int characterpos = cursorPosition.CharacterPosition;
//Update variables
selectionrenderer.SelectionStartPosition =
new CursorPosition(characterpos - Cursor.CalculateStepsToMoveLeft2(currentLine, characterpos), cursorPosition.LineNumber);
selectionrenderer.SelectionEndPosition =
new CursorPosition(characterpos + Cursor.CalculateStepsToMoveRight2(currentLine, characterpos), cursorPosition.LineNumber);
cursorPosition.CharacterPosition = selectionrenderer.SelectionEndPosition.CharacterPosition;
selectionrenderer.HasSelection = true;
//Render it
canvashelper.UpdateSelection();
canvashelper.UpdateCursor();
}
}
}

View File

@ -1,20 +0,0 @@
using TextControlBoxNS.Helper;
namespace TextControlBoxNS.Text
{
internal class StringManager
{
private TabSpaceHelper tabSpaceHelper;
public LineEnding lineEnding;
public StringManager(TabSpaceHelper tabSpaceHelper)
{
this.tabSpaceHelper = tabSpaceHelper;
}
public string CleanUpString(string input)
{
//Fix tabs and lineendings
return tabSpaceHelper.UpdateTabs(LineEndings.CleanLineEndings(input, lineEnding));
}
}
}

View File

@ -1,92 +0,0 @@
using Collections.Pooled;
using TextControlBoxNS.Extensions;
namespace TextControlBoxNS.Text
{
internal class TabKey
{
public static TextSelection MoveTabBack(PooledList<string> totalLines, TextSelection textSelection, CursorPosition cursorPosition, string tabCharacter, string newLineCharacter, UndoRedo undoRedo)
{
if (textSelection == null)
{
string line = totalLines.GetLineText(cursorPosition.LineNumber);
if (line.Contains(tabCharacter, System.StringComparison.Ordinal) && cursorPosition.CharacterPosition > 0)
cursorPosition.SubtractFromCharacterPos(tabCharacter.Length);
undoRedo.RecordUndoAction(() =>
{
totalLines.SetLineText(cursorPosition.LineNumber, line.RemoveFirstOccurence(tabCharacter));
}, totalLines, cursorPosition.LineNumber, 1, 1, newLineCharacter);
return new TextSelection(cursorPosition, null);
}
textSelection = Selection.OrderTextSelection(textSelection);
int selectedLinesCount = textSelection.EndPosition.LineNumber - textSelection.StartPosition.LineNumber;
TextSelection tempSel = new TextSelection(textSelection);
tempSel.StartPosition.CharacterPosition = 0;
tempSel.EndPosition.CharacterPosition = totalLines.GetLineText(textSelection.EndPosition.LineNumber).Length + tabCharacter.Length;
undoRedo.RecordUndoAction(() =>
{
for (int i = 0; i < selectedLinesCount + 1; i++)
{
int lineIndex = i + textSelection.StartPosition.LineNumber;
string currentLine = totalLines.GetLineText(lineIndex);
if (i == 0 && currentLine.Contains(tabCharacter, System.StringComparison.Ordinal) && cursorPosition.CharacterPosition > 0)
textSelection.StartPosition.CharacterPosition -= tabCharacter.Length;
else if (i == selectedLinesCount && currentLine.Contains(tabCharacter, System.StringComparison.Ordinal))
{
textSelection.EndPosition.CharacterPosition -= tabCharacter.Length;
}
totalLines.SetLineText(lineIndex, currentLine.RemoveFirstOccurence(tabCharacter));
}
}, totalLines, tempSel, selectedLinesCount, newLineCharacter);
return new TextSelection(new CursorPosition(textSelection.StartPosition), new CursorPosition(textSelection.EndPosition));
}
public static TextSelection MoveTab(PooledList<string> totalLines, TextSelection textSelection, CursorPosition cursorPosition, string tabCharacter, string newLineCharacter, UndoRedo undoRedo)
{
if (textSelection == null)
{
string line = totalLines.GetLineText(cursorPosition.LineNumber);
undoRedo.RecordUndoAction(() =>
{
totalLines.SetLineText(cursorPosition.LineNumber, line.AddText(tabCharacter, cursorPosition.CharacterPosition));
}, totalLines, cursorPosition.LineNumber, 1, 1, newLineCharacter);
cursorPosition.AddToCharacterPos(tabCharacter.Length);
return new TextSelection(cursorPosition, null);
}
textSelection = Selection.OrderTextSelection(textSelection);
int selectedLinesCount = textSelection.EndPosition.LineNumber - textSelection.StartPosition.LineNumber;
if (textSelection.StartPosition.LineNumber == textSelection.EndPosition.LineNumber) //Singleline
textSelection.StartPosition = Selection.Replace(textSelection, totalLines, tabCharacter, newLineCharacter);
else
{
TextSelection tempSel = new TextSelection(textSelection);
tempSel.StartPosition.CharacterPosition = 0;
tempSel.EndPosition.CharacterPosition = totalLines.GetLineText(textSelection.EndPosition.LineNumber).Length + tabCharacter.Length;
textSelection.EndPosition.CharacterPosition += tabCharacter.Length;
textSelection.StartPosition.CharacterPosition += tabCharacter.Length;
undoRedo.RecordUndoAction(() =>
{
for (int i = textSelection.StartPosition.LineNumber; i < selectedLinesCount + textSelection.StartPosition.LineNumber + 1; i++)
{
totalLines.SetLineText(i, totalLines.GetLineText(i).AddToStart(tabCharacter));
}
}, totalLines, tempSel, selectedLinesCount + 1, newLineCharacter);
}
return new TextSelection(new CursorPosition(textSelection.StartPosition), new CursorPosition(textSelection.EndPosition));
}
}
}

View File

@ -1,176 +0,0 @@
using Collections.Pooled;
using System;
using System.Collections.Generic;
using TextControlBoxNS.Extensions;
using TextControlBoxNS.Helper;
using TextControlBoxNS.Models;
namespace TextControlBoxNS.Text
{
internal class UndoRedo
{
private Stack<UndoRedoItem> UndoStack = new Stack<UndoRedoItem>();
private Stack<UndoRedoItem> RedoStack = new Stack<UndoRedoItem>();
private bool HasRedone = false;
private void RecordRedo(UndoRedoItem item)
{
RedoStack.Push(item);
}
private void RecordUndo(UndoRedoItem item)
{
UndoStack.Push(item);
}
private void AddUndoItem(TextSelection selection, int startLine, string undoText, string redoText, int undoCount, int redoCount)
{
UndoStack.Push(new UndoRedoItem
{
RedoText = redoText,
UndoText = undoText,
Selection = selection,
StartLine = startLine,
UndoCount = undoCount,
RedoCount = redoCount,
});
}
private void RecordSingleLine(Action action, PooledList<string> totalLines, int startline)
{
var lineBefore = totalLines.GetLineText(startline);
action.Invoke();
var lineAfter = totalLines.GetLineText(startline);
AddUndoItem(null, startline, lineBefore, lineAfter, 1, 1);
}
public void RecordUndoAction(Action action, PooledList<string> totalLines, int startline, int undocount, int redoCount, string newLineCharacter, CursorPosition cursorposition = null)
{
if (undocount == redoCount && redoCount == 1)
{
RecordSingleLine(action, totalLines, startline);
return;
}
var linesBefore = totalLines.GetLines(startline, undocount).GetString(newLineCharacter);
action.Invoke();
var linesAfter = totalLines.GetLines(startline, redoCount).GetString(newLineCharacter);
AddUndoItem(cursorposition == null ? null : new TextSelection(new CursorPosition(cursorposition), null), startline, linesBefore, linesAfter, undocount, redoCount);
}
public void RecordUndoAction(Action action, PooledList<string> totalLines, TextSelection selection, int numberOfAddedLines, string newLineCharacter)
{
var orderedSel = Selection.OrderTextSelection(selection);
if (orderedSel.StartPosition.LineNumber == orderedSel.EndPosition.LineNumber && orderedSel.StartPosition.LineNumber == 1)
{
RecordSingleLine(action, totalLines, orderedSel.StartPosition.LineNumber);
return;
}
int numberOfRemovedLines = orderedSel.EndPosition.LineNumber - orderedSel.StartPosition.LineNumber + 1;
if (numberOfAddedLines == 0 && !Selection.WholeLinesAreSelected(selection, totalLines) ||
orderedSel.StartPosition.LineNumber == orderedSel.EndPosition.LineNumber && orderedSel.Length == totalLines.GetLineLength(orderedSel.StartPosition.LineNumber))
numberOfAddedLines += 1;
var linesBefore = totalLines.GetLines(orderedSel.StartPosition.LineNumber, numberOfRemovedLines).GetString(newLineCharacter);
action.Invoke();
var linesAfter = totalLines.GetLines(orderedSel.StartPosition.LineNumber, numberOfAddedLines).GetString(newLineCharacter);
AddUndoItem(
selection,
orderedSel.StartPosition.LineNumber,
linesBefore,
linesAfter,
numberOfRemovedLines,
numberOfAddedLines
);
}
public TextSelection Undo(PooledList<string> totalLines, StringManager stringManager, string newLineCharacter)
{
if (UndoStack.Count < 1)
return null;
if (HasRedone)
{
HasRedone = false;
while (RedoStack.Count > 0)
{
var redoItem = RedoStack.Pop();
redoItem.UndoText = redoItem.RedoText = null;
}
}
UndoRedoItem item = UndoStack.Pop();
RecordRedo(item);
//Faster for singleline
if (item.UndoCount == 1 && item.RedoCount == 1)
{
totalLines.SetLineText(item.StartLine, stringManager.CleanUpString(item.UndoText));
}
else
{
totalLines.Safe_RemoveRange(item.StartLine, item.RedoCount);
if (item.UndoCount > 0)
totalLines.InsertOrAddRange(ListHelper.GetLinesFromString(stringManager.CleanUpString(item.UndoText), newLineCharacter), item.StartLine);
}
return item.Selection;
}
public TextSelection Redo(PooledList<string> totalLines, StringManager stringmanager, string newLineCharacter)
{
if (RedoStack.Count < 1)
return null;
UndoRedoItem item = RedoStack.Pop();
RecordUndo(item);
HasRedone = true;
//Faster for singleline
if (item.UndoCount == 1 && item.RedoCount == 1)
{
totalLines.SetLineText(item.StartLine, stringmanager.CleanUpString(item.RedoText));
}
else
{
totalLines.Safe_RemoveRange(item.StartLine, item.UndoCount);
if (item.RedoCount > 0)
totalLines.InsertOrAddRange(ListHelper.GetLinesFromString(stringmanager.CleanUpString(item.RedoText), newLineCharacter), item.StartLine);
}
return null;
}
/// <summary>
/// Clears all the items in the undo and redo stack
/// </summary>
public void ClearAll()
{
UndoStack.Clear();
RedoStack.Clear();
UndoStack.TrimExcess();
RedoStack.TrimExcess();
GC.Collect(GC.GetGeneration(UndoStack), GCCollectionMode.Optimized);
GC.Collect(GC.GetGeneration(RedoStack), GCCollectionMode.Optimized);
}
public void NullAll()
{
UndoStack = null;
RedoStack = null;
}
/// <summary>
/// Gets if the undo stack contains actions
/// </summary>
public bool CanUndo { get => UndoStack.Count > 0; }
/// <summary>
/// Gets if the redo stack contains actions
/// </summary>
public bool CanRedo { get => RedoStack.Count > 0; }
}
}

View File

@ -1,32 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>TextControlBoxNS</RootNamespace>
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<UseWinUI>true</UseWinUI>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<DocumentationFile></DocumentationFile>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<PackageId>TextControlBox.WinUI.JuliusKirsch</PackageId>
<Title>TextControlBox WinUI</Title>
<Version>1.0.0</Version>
<Authors>Julius Kirsch</Authors>
<Product>TextControlBox WinUI</Product>
<Description>A textbox for WinUI3 with syntax highlighting, line numbering, and support for a large amount of text</Description>
<Copyright>Julius Kirsch</Copyright>
<PackageProjectUrl>https://github.com/FrozenAssassine/TextControlBox-WinUI</PackageProjectUrl>
<RepositoryUrl>https://github.com/FrozenAssassine/TextControlBox-WinUI</RepositoryUrl>
<PackageTags>TextControlBox; Textbox; WinUI; C#; SyntaxHighlighting; LineNumbers</PackageTags>
<PackageReleaseNotes>Migrated from UWP to WinUI.</PackageReleaseNotes>
<PackageIcon>Icon1.png</PackageIcon>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Collections.Pooled" Version="1.0.82" />
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.0.5.1" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.2.221109.1" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.755" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project>

View File

@ -1,117 +0,0 @@
<UserControl
x:Class="TextControlBoxNS.TextControlBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helper="using:TextControlBoxNS.Helper"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xaml="using:Microsoft.Graphics.Canvas.UI.Xaml"
d:DesignHeight="300"
d:DesignWidth="400"
AllowDrop="True"
AllowFocusOnInteraction="false"
DragOver="UserControl_DragOver"
Drop="UserControl_Drop"
GotFocus="UserControl_GotFocus"
IsTabStop="True"
LosingFocus="UserControl_LosingFocus"
LostFocus="UserControl_LostFocus"
PointerEntered="UserControl_PointerEntered"
PointerExited="UserControl_PointerExited"
PointerWheelChanged="Canvas_Selection_PointerWheelChanged"
TabIndex="0"
Tapped="UserControl_Tapped"
mc:Ignorable="d">
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<xaml:CanvasControl
x:Name="Canvas_LineNumber"
Grid.Column="0"
Width="100"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
Draw="Canvas_LineNumber_Draw"
PointerEntered="Canvas_LineNumber_PointerEntered"
PointerExited="Canvas_LineNumber_PointerExited"
PointerPressed="Canvas_LineNumber_PointerPressed"
PointerReleased="Canvas_Selection_PointerReleased"
PointerWheelChanged="Canvas_Selection_PointerWheelChanged" />
<Grid x:Name="Scroll" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<xaml:CanvasControl
x:Name="Canvas_Cursor"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Draw="Canvas_Cursor_Draw" />
<xaml:CanvasControl
x:Name="Canvas_Text"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Draw="Canvas_Text_Draw" />
<xaml:CanvasControl
x:Name="Canvas_Selection"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Draw="Canvas_Selection_Draw"
PointerMoved="Canvas_Selection_PointerMoved"
PointerPressed="Canvas_Selection_PointerPressed"
PointerReleased="Canvas_Selection_PointerReleased" />
<ScrollBar
x:Name="VerticalScrollbar"
Grid.Column="2"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Background="Transparent"
IndicatorMode="MouseIndicator"
LargeChange="100"
Loaded="VerticalScrollbar_Loaded"
Maximum="0"
Minimum="0"
Orientation="Vertical"
PointerEntered="Scrollbar_PointerEntered"
PointerExited="Scrollbar_PointerExited"
Scroll="VerticalScrollbar_Scroll"
SmallChange="10"
Value="0" />
<ScrollBar
x:Name="HorizontalScrollbar"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Background="Transparent"
IndicatorMode="MouseIndicator"
LargeChange="100"
Maximum="0"
Minimum="0"
Orientation="Horizontal"
PointerEntered="Scrollbar_PointerEntered"
PointerExited="Scrollbar_PointerExited"
Scroll="HorizontalScrollbar_Scroll"
SmallChange="10"
Value="0" />
</Grid>
<helper:InputHandlerControl
x:Name="inputHandler"
Grid.Column="1"
Width="0"
Height="0"
GotFocus="UserControl_GotFocus"
LostFocus="UserControl_LostFocus"
Opacity="0"
PreviewKeyDown="InputHandler_KeyDown"
TextChanged="InputHandler_TextChanged" />
</Grid>
</UserControl>

File diff suppressed because it is too large Load Diff