Регулярная Авалония

в 18:33, , рубрики: .net, avalonia, avaloniaui, C#, Программирование, Разработка под Linux, разработка под windows

Иногда мы не понимаем как работает регулярное выражение, которое мы составили, и хотим проверить. Есть множество восхитительных приложений встроенных в различные среды или онлайн. Мне захотелось добавить еще одно к этому списку.
В данной статье мы посмотрим, как можно обернуть Regex в кроссплатформенную графику и получить простенькое приложение для теста регулярных выражений.
Регулярная Авалония - 1

Начало

Для того, чтобы создать проект с использованием avalonia ui нужно установить шаблоны с GitHub.
И создать проект из шаблона mvvm.

dotnet new avalonia.mvvm -o MyApp

Дизайн и разметка

Для создания основного окна разместим все компоненты внутри грида.

 <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="5" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="5" />
            <RowDefinition Height="*" />
            <RowDefinition Height="5" />
        </Grid.RowDefinitions>
    </Grid>

Наше приложение состоит из 2‑х частей: верхнего аналога тулбара и рабочей области.
Регулярная Авалония - 2

Рассмотрим верхнюю часть

Тут у нас поле для ввода регулярного выражения, чекбокс, показывающий, как анализировать текст (построчно или как целый фрагмент) и кнопка справки.
В качестве контейнера выступает Док панель. Данный контрол позволяет легко заполнить контейнер элементами, прижимая их к разным сторонам и гарантируя отсутствие свободного места внутри.

 <DockPanel Grid.Row="1">

И заполняем ее полем для ввода текста:

 <TextBox Margin="5, 0, 5, 0" Watermark="Your regexp" AcceptsReturn="False"  Text="{Binding RegText}"/>

Здесь стоит отметить приятную мелочь для Avalonia ui — наличие watermark у текстовых полей.
Добавим на панель чекбокс, имеющий 2 состояния, о чем говорит IsThreeState=«False»:

 <CheckBox DockPanel.Dock="Right" Content="By row" IsThreeState="False" IsChecked="{Binding IsChecked}" ToolTip.Tip="Check for each row" />

И кнопку, отвечающую за вызов справки:

 <Button DockPanel.Dock="Right" Content=" ? " Margin="5, 0, 5, 0" ToolTip.Tip="Show hints" Command="{Binding ShowHelp}" />

Основная часть
Рабочая часть будет помещена в грид:

 <Grid Grid.Row="3">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="0.75*" />
            </Grid.ColumnDefinitions>
        </Grid>

Поле ввода представлено текст боксом:

 <TextBox Grid.Column="0" AcceptsReturn="True" ScrollViewer.VerticalScrollBarVisibility="Auto" Text="{Binding InputText}"/>

Сплиттер позволяет подобрать удобную визуализацию под свои нужды:

  <GridSplitter Grid.Column="1" />

А поле, отвечающее за отображение результата применения регулярных выражений поместим в бордер так как текст блок не обладает собственной рамкой:

  <Border BorderBrush="Gray" BorderThickness="1" Grid.Column="2">
                <TextBlock  ScrollViewer.VerticalScrollBarVisibility="Auto" Text="{Binding OutputText}" />
            </Border>

Окно справки
Регулярная Авалония - 3
для создания нового окна обратимся к терминалу

dotnet new avalonia.window -na MyApp -n MyNewWindow

Данное окно будет содержать лишь справочную информацию и больше ничего, так что, проигнорировав контейнеры, сделаем лист бокс дочерним элементом для данного окна:

 <ListBox ScrollViewer.VerticalScrollBarVisibility="Visible" VirtualizationMode="None">
 </ListBox>

И заполним его одинаковыми элементами по мере необходимости:

     <ListBoxItem>
            <StackPanel Orientation="Horizontal">
                <TextBlock Margin="5"  Text="A single character of: a, b or c" />
                <TextBlock Margin="5"  Classes="green" Text="[abc]" />
            </StackPanel>
        </ListBoxItem>

Разметка достаточно простая: стек панель с 2 полями, единственное что здесь стоит отметить — атрибут Classes, что позволит стилизовать наши окна наподобие css (еще одна приятная фишка Авалонии.
И собственно покрасим сами правила в зеленый цвет:

 <Window.Styles>
        <Style Selector="TextBlock.green">
            <Setter Property="Foreground" Value="Green" />
        </Style>
    </Window.Styles>

Функциональность mvvm

В первую очередь озаботимся полями для всех элементов разметки:

private bool _isChecked;
private string _inputText;
private string _regText;
private string _outputText;

Создадим методы, которые вернут результаты матчинга с исходным тесктом:

private void SetNoRowResult()
        {
            OutputText = string.Join(Environment.NewLine,new Regex(_regText).Matches(_inputText));
        }

И с исходным текстом по линиям, для чего применим Split

 private void SetRowResult()
        {
            var r = new Regex(_regText);
            var s = string.Empty;
            foreach (var line in _inputText.Split( Environment.NewLine,StringSplitOptions.RemoveEmptyEntries))
            {
               
                s += $"--{Environment.NewLine}";
                s+=string.Join(Environment.NewLine,r.Matches(line));
                s += $"{Environment.NewLine}--{Environment.NewLine}";
            }

            OutputText = s;
        }

И добавим метод, отображающий окно справки

public void ShowHelp()
        {
            new HelpWindow().Show();
        }

Свойства и биндинги
Интересной особенностью Авалонии является возможность прибиндить метод напрямую к кнопке:

<Button  Command="{Binding ShowHelp}" />

Чем мы и воспользуемся.
Для остальных полей мы просто прибиндимся к свойствам. Здесь также интересной особенностью является то, что в авалонии обновление привязки происходит при изменении содержимого контрола, что в впф делалось так: UpdateSourceTrigger=PropertyChanged в авалонии работает по умолчанию.
А так как шаблон mvvm авалонии связан с Reactive UI, то и свойства создаются с использованием данной библиотеки:

public string RegText
        {
            get => _regText;
            set
            {
                this.RaiseAndSetIfChanged(ref _regText, value);
                if(_isChecked) SetRowResult();
                else SetNoRowResult();
            }
        }

В заключение
Я надеюсь, что данная статья заинтересует не только тех, кто захочет использовать мой материал иили как-то улучшить его, но и всех тех, кто знакомится с авалонией или ищет возможности создания кроссплатформенных приложений на c#.
Исходный код (тык).
Хотелось бы сказать спасибо ForNeVeR kekekeks worldbeater
И отметить, что поддержку по c# можно найти тут, а по авалонии вот тут.

Автор: Larymar

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js