Skip to content

Commit

Permalink
Почти работает deXAMLize
Browse files Browse the repository at this point in the history
  • Loading branch information
ComradeAkei committed Nov 12, 2023
1 parent 64b7d6e commit f8f4f8d
Show file tree
Hide file tree
Showing 13 changed files with 405 additions and 79 deletions.
224 changes: 224 additions & 0 deletions DeXAMLize.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace Xamlade;

public partial class MainWindow
{
private static string filePathXAML = "";
private static string ExternalXAML = "";

private static readonly string[] elementsToReplace =
{
"Border", "Canvas", "DockPanel", "Grid", "Panel", "ScrollViewer", "StackPanel",
"TabControl", "TabItem", "Button", "CheckBox", "ComboBox", "DatePicker",
"ListBox", "ListView", "Menu", "MenuItem", "ProgressBar", "RadioButton",
"Slider", "TextBox", "ToggleButton", "TextBlock", "Image"
};

public async Task RunDeXAMLIZE(Window window)
{
await OpenXAML(window);
await CorrectXAML();
await LoadXAML();
}

private async Task LoadXAML()
{
// Удаляем элементы из MainCanvas
for (int i = MainCanvas.jChildren.Count - 1; i >= 0; i--)
{
MainCanvas.RemoveChild(MainCanvas.jChildren[i]);
}

//Радикальная операция
//УЧЁТНЫЙ НОМЕР: 1_KILLALL
Broadcast.KillAll();


var obj = AvaloniaRuntimeXamlLoader.Load(ExternalXAML, typeof(MainWindow).Assembly) as Canvas;


var buf = new List<JControl>();
var canv_left = new List<double>();
var canv_top = new List<double>();
for (int j = obj.Children.Count - 1; j >= 0; j--)
{
buf.Add(obj.Children[j] as JControl);
canv_top.Add(Canvas.GetTop(obj.Children[j]));
canv_left.Add(Canvas.GetLeft(obj.Children[j]));
obj.Children.RemoveAt(j);
}

foreach (var item in buf)
{
MainCanvas.AddChild(item);
}

for (int i = 0; i < buf.Count; i++)
{
Canvas.SetTop(MainCanvas.Children[i], canv_top[i]);
Canvas.SetLeft(MainCanvas.Children[i], canv_left[i]);
}

Broadcast.RestoreBehavior();
}

public void CorrectLoadedjElement(JControl element)
{
element.Name ??= element.Type + "_" + (i++);


if (element.Name != "MainCanvas")
{
var parent = ((Control)element).Parent;

element.SetParent((IChildContainer)parent);



// element.SetParent(element);
element.PointerEntered += OnjControlPointerEntered;
element.PointerExited += OnjControlPointerExited;
element.Click += jElementClick;
element.PointerPressed += OnjControlPressed;
element.PointerReleased += OnjControlReleased;
}

if (element is IChildContainer)
{
var container = (IChildContainer)element;
foreach (var child in container.jChildren)
{
element.mTreeItem.Items.Add(ref child.mTreeItem);
}
}

selectedTreeItem = MainCanvas.mTreeItem;

}

private async Task OpenXAML(Window window)
{
filePathXAML = "";
ExternalXAML = "";


OpenFileDialog dialog = new OpenFileDialog();
dialog.Title = "Выберите XAML";
dialog.AllowMultiple = false;
dialog.Filters.Add(new FileDialogFilter
{
Name = "Файл разметки XAML",
Extensions = { "xaml", "axaml" }
});
Task<string[]> task = dialog.ShowAsync(window);

// Дожидаемся завершения задачи (await)
string[] result = await task;

// Обрабатываем результат
if (result != null && result.Length > 0)
{
filePathXAML = result[0];
ExternalXAML = File.ReadAllText(filePathXAML);
}
}

public static async Task CorrectXAML()
{
ExternalXAML = ReplaceElements(ExternalXAML, elementsToReplace);
ExternalXAML = RemoveWindowTags(ExternalXAML);
ExternalXAML = ReplaceMainCanvasTag(ExternalXAML);
File.WriteAllText(filePathXAML + "1", ExternalXAML);
}

static string ReplaceElements(string input, string[] elements)
{
// <Имя_элемента>
string openTagPattern = @"<({0})\b([^>]*)>";
//</Имя_элемента>
string closeTagPattern = @"<\/({0})>";

int index = 0;

foreach (var element in elements)
{
// Строим паттерны с учетом текущего элемента
string formattedOpenTagPattern = string.Format(openTagPattern, element);
string formattedCloseTagPattern = string.Format(closeTagPattern, element);

// Заменяем открывающие теги
input = Regex.Replace(input, formattedOpenTagPattern, match =>
{
var matchValue = match.Value;

// Заменяем <Имя_элемента на <xamlade:jИмя элемента
var replacement = matchValue.Replace("<" + element, "<xamlade:j" + element);

index++;

return replacement;
});

// Заменяем закрывающие теги
input = Regex.Replace(input, formattedCloseTagPattern, match =>
{
var matchValue = match.Value;
// Заменяем </Имя_элемента на </xamlade:jИмя элемента
var replacement = matchValue.Replace("</" + element, "</xamlade:j" + element);

index++;

return replacement;
});
}

return input;
}

static string RemoveWindowTags(string input)
{
// Паттерн для поиска открывающего и закрывающего тегов <Window ...> и </Window>
string pattern = @"<Window\b[^>]*>(.*?)</Window>";

// Заменяем совпадение на содержимое между тегами
return Regex.Replace(input, pattern, m => m.Groups[1].Value, RegexOptions.Singleline);
}

static string ReplaceMainCanvasTag(string input)
{
Match match = Regex.Match(input, @"<xamlade:jCanvas", RegexOptions.Singleline);

// Если найдено, заменяем его
if (match.Success)
{
// Заменяем только первое вхождение
int index = match.Index;
int length = match.Length;
input = input.Substring(0, index) +
"<Canvas xmlns='https://github.com/avaloniaui' xmlns:xamlade='clr-namespace:Xamlade'" +
input.Substring(index + length);

// Находим последнее вхождение </xamlade:jCanvas>
Match lastMatch = Regex.Match(input, @"</xamlade:jCanvas>",
RegexOptions.Singleline | RegexOptions.RightToLeft);

// Если найдено, заменяем его
if (lastMatch.Success)
{
index = lastMatch.Index;
length = lastMatch.Length;
input = input.Substring(0, index) + "</Canvas>" + input.Substring(index + length);
}
}

return input;
}
}
17 changes: 8 additions & 9 deletions ElementGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ public static void SetDefaultValues(JControl element)
{
switch (element.Type)
{
case ControlType.Button:
case "Button":
{
((jButton)element).Content = "Text";
((jButton)element).Background = Brushes.Blue;
((jButton)element).Foreground = Brushes.White;
((jButton)element).FontSize = 20;
}
break;
case ControlType.TextBox:
case "TextBox":
{
((jTextBox)element).Background = Brushes.Transparent;
((jTextBox)element).Text = "Text";
Expand All @@ -63,25 +63,24 @@ public static void SetDefaultValues(JControl element)

}
break;
case ControlType.TextBlock:
case "TextBlock":
{
((jTextBlock)element).Background = Brushes.Blue;
((jTextBlock)element).Text = "Text";
((jTextBlock)element).FontSize = 20;
((jTextBlock)element).Foreground = Brushes.White;
}
break;
case ControlType.Image:
case "Image":
{

((jImage)element).Source = new Bitmap("assets/Xamlade.png");
((jImage)element).Width = 400;
((jImage)element).Height = 400;
((jImage)element).jImageSource = @"assets/Xamlade.png";
((jImage)element).Background = Brushes.Blue;
}
break;
case ControlType.ToggleButton:
case "ToggleButton":
{
// ((jTextBlock)element).Background = Brushes.Blue;
((ToggleButton)element).Content = "Text";
Expand All @@ -90,15 +89,15 @@ public static void SetDefaultValues(JControl element)
// ((jTextBlock)element).Foreground = Brushes.White;
}
break;
case ControlType.CheckBox:
case "CheckBox":
{
((jCheckBox)element).Background = Brushes.Blue;
((jCheckBox)element).Content = "Text";
((jCheckBox)element).FontSize = 20;
((jCheckBox)element).Foreground = Brushes.White;
}
break;
case ContainerType.Canvas:
case "Canvas":
{
// Генерация случайного цвета в формате HEX
string randomHexColor = $"#{random.Next(0x1000000):X6}";
Expand All @@ -110,7 +109,7 @@ public static void SetDefaultValues(JControl element)

}
break;
case ContainerType.StackPanel:
case "StackPanel":
{
// Генерация случайного цвета в формате HEX
string randomHexColor = $"#{random.Next(0x1000000):X6}";
Expand Down
4 changes: 3 additions & 1 deletion MainWindow.axaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xamlade="clr-namespace:Xamlade"

xmlns:gif="clr-namespace:Avalonia.Gif;assembly=Avalonia.Gif"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:avaloniaColorPicker="clr-namespace:AvaloniaColorPicker;assembly=AvaloniaColorPicker"
Expand All @@ -17,6 +18,7 @@
<Button Width="150" Content="Run Window" Click="RUN_WINDOW" Margin="10" Background="#3A8FB7" />
<Button Width="150" Content="XAMLize!" Click="XAMLIZE" Margin="10" Background="#3A8FB7" />
<Button Width="150" Content="Remove" Click="RemovejElement" Margin="10" Background="#3A8FB7" />
<Button Width="150" Content="DEXAMLIZE" Click="DEXAMLIZE" Margin="10" Background="#3A8FB7" />
<Button Width="150" Content="DEBUG" Click="DEBUG" Margin="10" Background="#3A8FB7" />
<gif:GifImage Name="LoadingGif" IsVisible="False" SourceUriRaw="{Binding Path=SelectedGif}"
Stretch="None"
Expand Down Expand Up @@ -64,7 +66,7 @@
<TabItem Header="Свойства">
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<StackPanel Name="PropertyPanel" Width="300" Background="#2B2B2B">
<ListBox Name="PropListBox" ItemsSource="{Binding KeyValueList}" Width="300" Background="#2B2B2B">
<ListBox Name="PropListBox" Width="300" Background="#2B2B2B">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Padding" Value="0" />
Expand Down
23 changes: 12 additions & 11 deletions MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,15 @@
using Avalonia.Gif;
using Avalonia.Media.Imaging;
using AvaloniaColorPicker;
using Avalonia.Markup;

namespace Xamlade;

public class KeyValue
{
public string Key { get; set; }
public string? Value { get; set; }
}


public partial class MainWindow : Window
{
public static MainWindow _MainWindow;
public string SelectedGif => @"avares://Xamlade/RES/loading.gif";


Expand Down Expand Up @@ -59,12 +57,11 @@ public partial class MainWindow : Window

#endregion


public ObservableCollection<KeyValue> KeyValueList { get; set; }


public MainWindow()
{
KeyValueList = new ObservableCollection<KeyValue>();
_MainWindow = this;
InitializeComponent();
DataContext = this;
WindowState = WindowState.Maximized;
Expand Down Expand Up @@ -227,7 +224,6 @@ private void ShowProperties()
}
}


FieldInfo privateField =
typeof(ItemsControl).GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance);
privateField.SetValue(PropListBox, PropListItems);
Expand Down Expand Up @@ -490,11 +486,16 @@ public static async Task<string> ExecuteLinuxCommandAsync(string command)
return result;
}
}


private async void DEXAMLIZE(object? sender, RoutedEventArgs e)
{
await RunDeXAMLIZE(this);
}


private void DEBUG(object? sender, RoutedEventArgs e)
{

}


}
4 changes: 2 additions & 2 deletions Miscellaneous.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ private SolidColorBrush GetColor(string color)
//Корректировка координат для перемещения и растяжения в строгом режиме
double CorrectCoords(double coord)
{
if ((bool)!StrictModeEnabled.IsChecked) return coord;
if(StrictModeValue.Text == "") return coord;
if ((bool)!StrictModeEnabled.IsChecked) return Math.Round(coord);
if(StrictModeValue.Text == "") return Math.Round(coord);
int step = Convert.ToInt32(StrictModeValue.Text);
if (step <= 0) return coord;
var _coord = (((int)coord)/step)*step;
Expand Down
Loading

0 comments on commit f8f4f8d

Please sign in to comment.