Imports EgtUILib Imports EgtWPFLib5 Imports ICSharpCode.AvalonEdit.Document Imports ICSharpCode.AvalonEdit.Rendering Imports System.IO Imports System.Text Imports System.Text.RegularExpressions Public Class ScriptWindowVM Inherits VMBase #Region "FIELD & PROPERTIES" Private m_sNameFile As String = String.Empty Public Property sNameFile As String Get Return m_sNameFile End Get Set(value As String) m_sNameFile = value NotifyPropertyChanged(NameOf(sNameFile)) End Set End Property Private m_sScriptText As String = String.Empty Public Property sScriptText As String Get Return m_sScriptText End Get Set(value As String) m_sScriptText = value NotifyPropertyChanged(NameOf(sScriptText)) End Set End Property Private m_nFontSizeList As New List(Of Integer) Public Property FontSizeList As List(Of Integer) Get Return m_nFontSizeList End Get Set(value As List(Of Integer)) m_nFontSizeList = value NotifyPropertyChanged(NameOf(FontSizeList)) End Set End Property Private m_nSelFontSize As Integer Public Property SelFontSize As Integer Get Return m_nSelFontSize End Get Set(value As Integer) m_nSelFontSize = value If Not IsNothing(m_nSelFontSize) Then ChangeFontSize(m_nSelFontSize) NotifyPropertyChanged(NameOf(SelFontSize)) End Set End Property Friend Sub SetSelFontSize(value As Integer) m_nSelFontSize = value NotifyPropertyChanged(NameOf(SelFontSize)) End Sub Private m_sFontFamilyList As New List(Of FontFamily) Public Property FontFamilyList As List(Of FontFamily) Get Return m_sFontFamilyList End Get Set(value As List(Of FontFamily)) m_sFontFamilyList = value NotifyPropertyChanged(NameOf(FontFamilyList)) End Set End Property Private m_sSelFontFamily As FontFamily Public Property SelFontFamily As FontFamily Get Return m_sSelFontFamily End Get Set(value As FontFamily) m_sSelFontFamily = value If Not IsNothing(m_sSelFontFamily) Then ChangeFontFamily(m_sSelFontFamily) NotifyPropertyChanged(NameOf(SelFontFamily)) End Set End Property Friend Sub SetSelFontFamily(value As FontFamily) m_sSelFontFamily = value NotifyPropertyChanged(NameOf(SelFontFamily)) End Sub Private m_bBoldIsChecked As Boolean = False Public Property BoldIsChecked As Boolean Get Return m_bBoldIsChecked End Get Set(value As Boolean) m_bBoldIsChecked = value NotifyPropertyChanged(NameOf(BoldIsChecked)) End Set End Property Private m_bItalicIsChecked As Boolean = False Public Property ItalicIsChecked As Boolean Get Return m_bItalicIsChecked End Get Set(value As Boolean) m_bItalicIsChecked = value NotifyPropertyChanged(NameOf(ItalicIsChecked)) End Set End Property Private m_bUnderlineChecked As Boolean = False Public Property UnderlineChecked As Boolean Get Return m_bUnderlineChecked End Get Set(value As Boolean) m_bUnderlineChecked = value NotifyPropertyChanged(NameOf(UnderlineChecked)) End Set End Property #Region "Messages" Public ReadOnly Property Title As String Get Return EgtMsg(110076) ' Script File End Get End Property Public ReadOnly Property Conferma_Msg As String Get Return EgtMsg(110075) ' Esegui End Get End Property Public ReadOnly Property Salva_Msg As String Get Return EgtMsg(110013) ' Salva End Get End Property Public ReadOnly Property Annulla_Msg As String Get Return EgtMsg(110004) ' Annulla End Get End Property #End Region ' Messages ' Definizione Comandi Private m_ConfermaCmd As ICommand Private m_cmdSaveAs As ICommand Private m_cmdAnnulla As ICommand Private m_cmdTextColor As ICommand Private m_cmdBold As ICommand Private m_cmdItalic As ICommand Private m_cmdUnderline As ICommand Private m_cmdAllign As ICommand #End Region ' Fields & Properties #Region "CONSTRUCTOR" Sub New() Map.SetRefScriptWindowVM(Me) If m_nFontSizeList.Count <= 0 Then CreateFontSizeList() If m_sFontFamilyList.Count <= 0 Then CreateFontFamilyList() SetToolbar() End Sub #End Region ' Constructor #Region "METHODS" Public Function SaveProject() As Boolean ' Determina il nome del file di default Dim sFile As String = If(String.IsNullOrWhiteSpace(m_sNameFile), "New.lua", $"{m_sNameFile}.lua") sFile = IO.Path.ChangeExtension(sFile, "lua") ' Assegnazione nome file con dialogo Dim SaveFileDialog As New EgtManageFileDialogV(Application.Current.MainWindow, New EgtManageFileDialogVM()) With { .Title = EgtMsg(110013), ' Salva .Filter = "lua files (*.lua)|*.lua", .FileName = sFile, .FilterIndex = 1, .InitialDirectory = Map.refMainWindowVM.MainWindowM.sTempDir, .ValidateNames = False, .OverwritePrompt = True, .Mode = 1 } ' Mostra la finestra di dialogo e ottieni il percorso del file selezionato Dim sFileName As String = String.Empty If SaveFileDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then Dim fileExtension = IO.Path.GetExtension(SaveFileDialog.SafeFileName) sFileName = IO.Path.Combine(SaveFileDialog.InitialDirectory, SaveFileDialog.SafeFileName & If(String.IsNullOrEmpty(fileExtension), SaveFileDialog.SelFilter.sExstension.Trim("*"c), String.Empty)) End If ' Verifica se il nome del file è stato selezionato If String.IsNullOrWhiteSpace(sFileName) Then Return False ' Salva il progetto e scrive lo script Lua Dim bOk = Map.refSceneHostVM.SaveProj(sFileName) WriteTextScriptLua(sFileName) ' Imposta lo stato della scena Map.refSceneHostVM.MainScene.SetStatusNull() Return bOk End Function Private Sub WriteTextScriptLua(sFileName As String) If String.IsNullOrWhiteSpace(sFileName) Then Return ' Validazione input File.WriteAllText(sFileName, m_sScriptText, Encoding.UTF8) ' Salva il file con codifica UTF-8 End Sub Private Sub SaveScript(sPathFileScript As String, sScriptText As String) If String.IsNullOrWhiteSpace(sPathFileScript) OrElse String.IsNullOrWhiteSpace(sScriptText) Then Return ' Validazione input Map.refSceneHostVM.SaveProj(sPathFileScript) ' Salva il progetto nel percorso specificato File.WriteAllText(sPathFileScript, sScriptText, Encoding.UTF8) ' Salva il contenuto con codifica UTF-8 End Sub Public Sub SetColorScriptText() Map.refScriptWindowV.LuaEditor.TextArea.TextView.LineTransformers.Add(New LuaRegexColorizer()) End Sub Private Sub CreateFontSizeList() ' Aggiunge solo font-size pari alla lista, con un semplice iteratore m_nFontSizeList.AddRange(Enumerable.Range(8, 13).Where(Function(size) size Mod 2 = 0)) End Sub Private Sub CreateFontFamilyList() ' Aggiunge direttamente tutte le famiglie di font alla lista m_sFontFamilyList.AddRange(Fonts.SystemFontFamilies) End Sub Private Sub ApplyTextStyle(editor As ICSharpCode.AvalonEdit.TextEditor, colorizer As Object) Dim selectionStart As Integer = editor.SelectionStart Dim selectionLength As Integer = editor.SelectionLength ' Controlla se c'è una selezione valida If selectionLength > 0 Then ' Aggiungi il colorizer specifico per applicare lo stile editor.TextArea.TextView.LineTransformers.Add(colorizer) ' Ridisegna il controllo per applicare le modifiche editor.TextArea.TextView.Redraw() End If End Sub Private Sub ChangeFontSize(nSelFontSize As Integer) ' Passa un FontSizeColorizer al metodo ausiliario Dim editor = Map.refScriptWindowV.LuaEditor ApplyTextStyle(editor, New FontSizeColorizer(editor.SelectionStart, editor.SelectionLength, nSelFontSize)) End Sub Private Sub ChangeFontFamily(sSelFontFamily As FontFamily) ' Passa un FontFamilyColorizer al metodo ausiliario Dim editor = Map.refScriptWindowV.LuaEditor ApplyTextStyle(editor, New FontFamilyColorizer(editor.SelectionStart, editor.SelectionLength, sSelFontFamily)) End Sub Friend Sub SetToolbar() ' Recupera font e dimensione SetSelFontFamily(Map.refScriptWindowV.LuaEditor.FontFamily) SetSelFontSize(Map.refScriptWindowV.LuaEditor.FontSize) End Sub Private Sub ApplyTextEffect(editor As ICSharpCode.AvalonEdit.TextEditor, colorizer As Object) Dim selectionStart As Integer = editor.SelectionStart Dim selectionLength As Integer = editor.SelectionLength ' Verifica che ci sia una selezione valida If selectionLength > 0 Then ' Aggiungi il colorizer specifico per applicare l'effetto editor.TextArea.TextView.LineTransformers.Add(colorizer) ' Ridisegna il controllo per applicare le modifiche editor.TextArea.TextView.Redraw() End If End Sub Private Sub ApplyBoldToSelection(editor As ICSharpCode.AvalonEdit.TextEditor) ApplyTextEffect(editor, New BoldColorizer(editor.SelectionStart, editor.SelectionLength)) End Sub Private Sub ApplyItalicToSelection(editor As ICSharpCode.AvalonEdit.TextEditor) ApplyTextEffect(editor, New ItalicColorizer(editor.SelectionStart, editor.SelectionLength)) End Sub Private Sub ApplyUnderlineToSelection(editor As ICSharpCode.AvalonEdit.TextEditor) ApplyTextEffect(editor, New UnderlineColorizer(editor.SelectionStart, editor.SelectionLength)) End Sub #End Region ' Methods #Region "COMMANDS" #Region "ConfermCmd" Public ReadOnly Property ConfermaCmd As ICommand Get If m_ConfermaCmd Is Nothing Then m_ConfermaCmd = New Command(AddressOf Conferma) End If Return m_ConfermaCmd End Get End Property Public Sub Conferma() ' Genera il percorso del file script Dim scriptFilePath As String = IO.Path.Combine(Map.refMainWindowVM.MainWindowM.sTempDir, $"{m_sNameFile}.lua") ' Salva il file script SaveScript(scriptFilePath, m_sScriptText) ' Esegue il file script EgtLuaExecFile(scriptFilePath) ' Imposta lo stato della gestione mouse diretto della scena a "nessuno" Map.refSceneHostVM.MainScene.SetStatusNull() End Sub #End Region ' ConfermaCmd #Region "SaveAsCommand" Public ReadOnly Property SalvaCmd As ICommand Get If m_cmdSaveAs Is Nothing Then m_cmdSaveAs = New Command(AddressOf SaveAs) End If Return m_cmdSaveAs End Get End Property Public Sub SaveAs() SaveProject() End Sub #End Region ' SaveAsCommand #Region "AnnullaCmd" Public ReadOnly Property AnnullaCmd As ICommand Get If m_cmdAnnulla Is Nothing Then m_cmdAnnulla = New Command(AddressOf Annulla) End If Return m_cmdAnnulla End Get End Property Public Sub Annulla() Map.refScriptWindowV.Close() Map.refTopPanelVM.SetIsEnableScriptBtn(True) End Sub #End Region ' AnnullaCmd #Region "TextColorCmd" Public ReadOnly Property TextColorCmd As ICommand Get If m_cmdTextColor Is Nothing Then m_cmdTextColor = New Command(AddressOf TextColor) End If Return m_cmdTextColor End Get End Property Public Sub TextColor() ' Recupero colori custom Dim defaultColor As New Color3d(10, 122, 150) Dim sCustomColors As String = String.Empty GetMainPrivateProfileString(S_COLORS, K_CUSTOMCOLORS, "", sCustomColors) ' Parsing dei colori custom in una lista di interi Dim nCustomColors = sCustomColors.Split(","c). Select(Function(color) Dim nColor As Integer Return If(Integer.TryParse(color, nColor), nColor, Nothing) End Function). Where(Function(nColor) nColor > 0).Cast(Of Integer)().ToList() ' Configurazione dialogo colori Dim colorDialog As New EgtColorPickerV(Application.Current.MainWindow, New EgtColorPickerVM()) With { .CustomColors = nCustomColors.ToArray(), .Color = defaultColor.ToColor() } ' Visualizzo il dialogo e gestisco l'output If colorDialog.ShowDialog() <> Windows.Forms.DialogResult.OK Then Return ' Conversione colore selezionato Dim selectedColor As System.Windows.Media.Color = System.Windows.Media.Color.FromRgb( CByte(colorDialog.Color.R), CByte(colorDialog.Color.G), CByte(colorDialog.Color.B) ) ' Applicazione del colore al testo selezionato Dim selectedText As String = Map.refScriptWindowV.LuaEditor.SelectedText Dim selectionStart As Integer = Map.refScriptWindowV.LuaEditor.SelectionStart Dim selectionLength As Integer = Map.refScriptWindowV.LuaEditor.SelectionLength ' Controlla se c'è una selezione valida If selectionLength > 0 Then ' Colore di evidenziazione, ad esempio giallo Dim highlightColor As Color = Colors.Yellow ' Aggiungi il colorizer per evidenziare la selezione Map.refScriptWindowV.LuaEditor.TextArea.TextView.LineTransformers.Add(New SelectionColorizer(selectionStart, selectionLength, selectedColor)) ' Ridisegna il controllo per applicare le modifiche Map.refScriptWindowV.LuaEditor.TextArea.TextView.Redraw() End If End Sub #End Region ' TextColorCmd #Region "BoldCmd" Public ReadOnly Property BoldCmd As ICommand Get If m_cmdBold Is Nothing Then m_cmdBold = New Command(AddressOf ApplyBold) End If Return m_cmdBold End Get End Property Public Sub ApplyBold() ApplyBoldToSelection(Map.refScriptWindowV.LuaEditor) End Sub #End Region ' BoldCmd #Region "ItalicCmd" Public ReadOnly Property ItalicCmd As ICommand Get If m_cmdItalic Is Nothing Then m_cmdItalic = New Command(AddressOf ApplyItalic) End If Return m_cmdItalic End Get End Property Public Sub ApplyItalic() ApplyItalicToSelection(Map.refScriptWindowV.LuaEditor) End Sub #End Region ' ItalicCmd #Region "UnderlineCmd" Public ReadOnly Property UnderlineCmd As ICommand Get If m_cmdUnderline Is Nothing Then m_cmdUnderline = New Command(AddressOf ApplyUnderline) End If Return m_cmdUnderline End Get End Property Public Sub ApplyUnderline() ApplyUnderlineToSelection(Map.refScriptWindowV.LuaEditor) End Sub #End Region ' UnderlineCmd #End Region ' Commands End Class ' Classe per gestire la colorazione tramite Regex Public Class LuaRegexColorizer Inherits DocumentColorizingTransformer #Region "FIELDS & PROPERTIES" ' Dizionario con Regex Precompilate e Colori Associati Private patterns As New Dictionary(Of Regex, System.Windows.Media.Color) From { {RegexM.KeywordRegex, ColorScriptM.KeywordColor}, {RegexM.ValueRegex, ColorScriptM.ValueColor}, {RegexM.FunctionRegex, ColorScriptM.FunctionColor}, {RegexM.InfoRegex, ColorScriptM.InfoColor}, {RegexM.EgtRegex, ColorScriptM.EgtColor}, {RegexM.BracketRegex, ColorScriptM.BracketColor}, {RegexM.TextRegex, ColorScriptM.TextColor}, {RegexM.NumberRegex, ColorScriptM.NumberColor}, {RegexM.CommentRegex, ColorScriptM.CommentColor}, {RegexM.PointRegex, ColorScriptM.FreeColor}, {RegexM.TableRegex, ColorScriptM.EgtColor}, {RegexM.EqualRegex, ColorScriptM.FreeColor} } #End Region ' Fields & Properties #Region "METHODS" Protected Overrides Sub ColorizeLine(line As DocumentLine) ' Applicare evidenziazione per ogni regex nel dizionario For Each kvp In patterns Dim regex As Regex = kvp.Key Dim color As Color = kvp.Value ' Evidenzia le corrispondenze Dim matches As MatchCollection = regex.Matches(CurrentContext.Document.GetText(line)) For Each match As Match In matches ChangeLinePart(line.Offset + match.Index, line.Offset + match.Index + match.Length, Sub(visual As VisualLineElement) visual.TextRunProperties.SetForegroundBrush(New SolidColorBrush(color)) End Sub) Next Next End Sub #End Region ' Methods End Class ' Classe per gestire la colorazione quando viene selezionata una parola Public Class SelectionColorizer Inherits DocumentColorizingTransformer #Region "FIELDS & PROPERTIES" Private ReadOnly StartOffset As Integer Private ReadOnly Length As Integer Private ReadOnly HighlightBrush As Brush #End Region ' Fields & Properties #Region "CONSTRUCTOR" Public Sub New(startOffset As Integer, length As Integer, color As Color) Me.StartOffset = startOffset Me.Length = length Me.HighlightBrush = New SolidColorBrush(color) End Sub #End Region ' Constructor #Region "METHODS" Protected Overrides Sub ColorizeLine(line As DocumentLine) Dim lineStart As Integer = line.Offset Dim lineEnd As Integer = lineStart + line.Length ' Se la selezione non riguarda questa linea, termina If StartOffset >= lineEnd OrElse (StartOffset + Length) <= lineStart Then Return ' Calcola l'inizio e la fine dell'area da colorare Dim start As Integer = Math.Max(StartOffset, lineStart) Dim [end] As Integer = Math.Min(StartOffset + Length, lineEnd) ' Applica lo stile ChangeLinePart(start, [end], Sub(visualLineElement As VisualLineElement) visualLineElement.TextRunProperties.SetForegroundBrush(HighlightBrush) End Sub) End Sub #End Region ' Methods End Class ' Classe per gestire la dimensione di una parola selezionata Public Class FontSizeColorizer Inherits DocumentColorizingTransformer #Region "FIELDS & PROPERTIES" Private ReadOnly StartOffset As Integer Private ReadOnly Length As Integer Private ReadOnly FontSize As Double #End Region ' Field & Properties #Region "CONSTRUCTOR" Public Sub New(startOffset As Integer, length As Integer, fontSize As Double) Me.StartOffset = startOffset Me.Length = length Me.FontSize = fontSize End Sub #End Region ' Constructor #Region "METHODS" Protected Overrides Sub ColorizeLine(line As DocumentLine) Dim lineStart As Integer = line.Offset Dim lineEnd As Integer = lineStart + line.Length ' Se la selezione non riguarda questa linea, termina If StartOffset >= lineEnd OrElse (StartOffset + Length) <= lineStart Then Return ' Calcola l'inizio e la fine dell'area da modificare Dim start As Integer = Math.Max(StartOffset, lineStart) Dim [end] As Integer = Math.Min(StartOffset + Length, lineEnd) ' Applica la dimensione del font ChangeLinePart(start, [end], Sub(visualLineElement As VisualLineElement) visualLineElement.TextRunProperties.SetFontRenderingEmSize(FontSize) End Sub) End Sub #End Region ' Methods End Class ' Classe per gestire la famiglia dei caratteri di una parola selezionata Public Class FontFamilyColorizer Inherits DocumentColorizingTransformer #Region "FIELDS & PROPERTIES" Private ReadOnly StartOffset As Integer Private ReadOnly Length As Integer Private ReadOnly FontFamily As FontFamily #End Region ' Fields & Properties #Region "CONSTRUCTOR" Public Sub New(startOffset As Integer, length As Integer, fontFamily As FontFamily) Me.StartOffset = startOffset Me.Length = length Me.FontFamily = fontFamily End Sub #End Region ' Constructor #Region "METHODS" Protected Overrides Sub ColorizeLine(line As DocumentLine) Dim lineStart As Integer = line.Offset Dim lineEnd As Integer = lineStart + line.Length ' Se la selezione non riguarda questa linea, esci If StartOffset >= lineEnd OrElse (StartOffset + Length) <= lineStart Then Return ' Calcola i limiti della parte di testo da modificare Dim start As Integer = Math.Max(StartOffset, lineStart) Dim [end] As Integer = Math.Min(StartOffset + Length, lineEnd) ' Applica la nuova FontFamily ChangeLinePart(start, [end], Sub(visualLineElement As VisualLineElement) Dim properties = visualLineElement.TextRunProperties.Clone() Dim typeface = properties.Typeface visualLineElement.TextRunProperties.SetTypeface(New Typeface(FontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal)) End Sub) End Sub #End Region ' Methods End Class ' Classe per gestire il grassetto del testo Public Class BoldColorizer Inherits DocumentColorizingTransformer #Region "FIELDS & PROPERTIES" Private ReadOnly StartOffset As Integer Private ReadOnly Length As Integer #End Region ' Fields & Properties #Region "CONSTRUCTOR" Public Sub New(startOffset As Integer, length As Integer) Me.StartOffset = startOffset Me.Length = length End Sub #End Region ' Constructor #Region "METHODS" Protected Overrides Sub ColorizeLine(line As DocumentLine) Dim lineStart As Integer = line.Offset Dim lineEnd As Integer = lineStart + line.Length ' Se la selezione cade fuori dalla linea attuale, esci If StartOffset >= lineEnd OrElse (StartOffset + Length) <= lineStart Then Return ' Calcola l'inizio e la fine dell'area da colorare Dim start As Integer = Math.Max(StartOffset, lineStart) Dim [end] As Integer = Math.Min(StartOffset + Length, lineEnd) ' Applica il grassetto modificando il Typeface ChangeLinePart(start, [end], Sub(visualLineElement As VisualLineElement) Dim properties = visualLineElement.TextRunProperties.Clone() Dim typeface = properties.Typeface If Map.refScriptWindowVM.BoldIsChecked Then visualLineElement.TextRunProperties.SetTypeface(New Typeface(typeface.FontFamily, FontStyles.Normal, FontWeights.Bold, typeface.Stretch)) Else visualLineElement.TextRunProperties.SetTypeface(New Typeface(typeface.FontFamily, FontStyles.Normal, FontWeights.Normal, typeface.Stretch)) End If End Sub) End Sub #End Region ' Methods End Class ' Classe per gestire il corsivo del testo Public Class ItalicColorizer Inherits DocumentColorizingTransformer #Region "FIELDS & PROPERTIES" Private ReadOnly StartOffset As Integer Private ReadOnly Length As Integer #End Region ' Fields & Properties #Region "CONSTRUCTOR" Public Sub New(startOffset As Integer, length As Integer) Me.StartOffset = startOffset Me.Length = length End Sub #End Region ' Constructor #Region "METHODS" Protected Overrides Sub ColorizeLine(line As DocumentLine) Dim lineStart As Integer = line.Offset Dim lineEnd As Integer = lineStart + line.Length ' Controlla se la selezione cade nella linea attuale If StartOffset >= lineEnd OrElse (StartOffset + Length) <= lineStart Then Return ' Calcola l'inizio e la fine dell'area da stilizzare Dim start As Integer = Math.Max(StartOffset, lineStart) Dim [end] As Integer = Math.Min(StartOffset + Length, lineEnd) ' Applica il corsivo ChangeLinePart(start, [end], Sub(visualLineElement As VisualLineElement) Dim properties = visualLineElement.TextRunProperties.Clone() Dim typeface = properties.Typeface If Map.refScriptWindowVM.ItalicIsChecked Then visualLineElement.TextRunProperties.SetTypeface(New Typeface(typeface.FontFamily, FontStyles.Italic, typeface.Weight, typeface.Stretch)) Else visualLineElement.TextRunProperties.SetTypeface(New Typeface(typeface.FontFamily, FontStyles.Normal, typeface.Weight, typeface.Stretch)) End If End Sub) End Sub #End Region ' Methods End Class ' Classe per gestire il sottolineato del testo Public Class UnderlineColorizer Inherits DocumentColorizingTransformer #Region "FIELDS & PROPERTIES" Private ReadOnly StartOffset As Integer Private ReadOnly Length As Integer #End Region ' Fields & Properties #Region "CONSTRUCTOR" Public Sub New(startOffset As Integer, length As Integer) Me.StartOffset = startOffset Me.Length = length End Sub #End Region ' Constructor #Region "METHODS" Protected Overrides Sub ColorizeLine(line As DocumentLine) Dim lineStart As Integer = line.Offset Dim lineEnd As Integer = lineStart + line.Length ' Controlla se la selezione cade nella linea attuale If StartOffset >= lineEnd OrElse (StartOffset + Length) <= lineStart Then Return ' Calcola i limiti della parte di testo da sottolineare Dim start As Integer = Math.Max(StartOffset, lineStart) Dim [end] As Integer = Math.Min(StartOffset + Length, lineEnd) ' Applica la sottolineatura ChangeLinePart(start, [end], Sub(visualLineElement As VisualLineElement) ' Aggiungi le decorazioni di sottolineatura If Map.refScriptWindowVM.UnderlineChecked Then visualLineElement.TextRunProperties.SetTextDecorations(TextDecorations.Underline) Else visualLineElement.TextRunProperties.SetTextDecorations(Nothing) End If End Sub) End Sub #End Region ' Methods End Class