编译器QWQ
This commit is contained in:
parent
66a3c6526f
commit
871e195315
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
139
RustTools/Editor/EditorTreeView.cs
Normal file
139
RustTools/Editor/EditorTreeView.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
66
RustTools/RustTools - Backup.csproj
Normal file
66
RustTools/RustTools - Backup.csproj
Normal 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>
|
|
@ -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" />
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
namespace TextControlBoxNS
|
||||
{
|
||||
internal enum LineMoveDirection
|
||||
{
|
||||
Up, Down
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
|
@ -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}";
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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
Loading…
Reference in New Issue
Block a user