Added running log panel in the below screen
This commit is contained in:
@@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
@@ -25,6 +26,8 @@ namespace Nodify.Calculator
|
|||||||
_ => Editors.Count > 0 && SelectedEditor != null);
|
_ => Editors.Count > 0 && SelectedEditor != null);
|
||||||
RunFlowCommand = new DelegateCommand(() =>
|
RunFlowCommand = new DelegateCommand(() =>
|
||||||
{
|
{
|
||||||
|
if (LogPanel.IsRunning) return;
|
||||||
|
|
||||||
Executor ex = new Executor(Editors.First());
|
Executor ex = new Executor(Editors.First());
|
||||||
var result = ex.PerformPreCheck();
|
var result = ex.PerformPreCheck();
|
||||||
if (!string.IsNullOrEmpty(result))
|
if (!string.IsNullOrEmpty(result))
|
||||||
@@ -33,8 +36,21 @@ namespace Nodify.Calculator
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FlowRunner runner = new FlowRunner(ex);
|
LogPanel.LogEntries.Clear();
|
||||||
runner.ShowDialog();
|
LogPanel.IsOpen = true;
|
||||||
|
LogPanel.IsRunning = true;
|
||||||
|
ex.OnLogMe += LogPanel.WriteLog;
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ex.Execute();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Application.Current?.Dispatcher.Invoke(() => LogPanel.IsRunning = false);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
SaveFileCommand = new DelegateCommand(() =>
|
SaveFileCommand = new DelegateCommand(() =>
|
||||||
@@ -127,5 +143,7 @@ namespace Nodify.Calculator
|
|||||||
get => _autoSelectNewEditor;
|
get => _autoSelectNewEditor;
|
||||||
set => SetProperty(ref _autoSelectNewEditor, value);
|
set => SetProperty(ref _autoSelectNewEditor, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LogPanelViewModel LogPanel { get; } = new LogPanelViewModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
76
Examples/Nodify.Calculator/LogPanelViewModel.cs
Normal file
76
Examples/Nodify.Calculator/LogPanelViewModel.cs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace Nodify.Calculator
|
||||||
|
{
|
||||||
|
public class LogEntry
|
||||||
|
{
|
||||||
|
public string Timestamp { get; set; }
|
||||||
|
public string Level { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
public Brush Color { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LogPanelViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private bool _isOpen;
|
||||||
|
public bool IsOpen
|
||||||
|
{
|
||||||
|
get => _isOpen;
|
||||||
|
set => SetProperty(ref _isOpen, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isRunning;
|
||||||
|
public bool IsRunning
|
||||||
|
{
|
||||||
|
get => _isRunning;
|
||||||
|
set => SetProperty(ref _isRunning, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableCollection<LogEntry> LogEntries { get; } = new ObservableCollection<LogEntry>();
|
||||||
|
|
||||||
|
public INodifyCommand ClearLogsCommand { get; }
|
||||||
|
public INodifyCommand ClosePanelCommand { get; }
|
||||||
|
|
||||||
|
public LogPanelViewModel()
|
||||||
|
{
|
||||||
|
ClearLogsCommand = new DelegateCommand(() => LogEntries.Clear());
|
||||||
|
ClosePanelCommand = new DelegateCommand(() => IsOpen = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteLog(string message, logType logtype = logType.Information)
|
||||||
|
{
|
||||||
|
Brush color;
|
||||||
|
switch (logtype)
|
||||||
|
{
|
||||||
|
case logType.Warning:
|
||||||
|
color = Brushes.Orange;
|
||||||
|
break;
|
||||||
|
case logType.Error:
|
||||||
|
color = Brushes.OrangeRed;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
color = Brushes.White;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entry = new LogEntry
|
||||||
|
{
|
||||||
|
Timestamp = DateTime.Now.ToString("HH:mm:ss"),
|
||||||
|
Level = logtype.ToString(),
|
||||||
|
Message = message,
|
||||||
|
Color = color
|
||||||
|
};
|
||||||
|
|
||||||
|
if (System.Windows.Application.Current?.Dispatcher.CheckAccess() == true)
|
||||||
|
{
|
||||||
|
LogEntries.Add(entry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.Windows.Application.Current?.Dispatcher.Invoke(() => LogEntries.Add(entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,7 +51,14 @@
|
|||||||
</Window.Resources>
|
</Window.Resources>
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<shared:TabControlEx ItemsSource="{Binding Editors}"
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" MinHeight="0" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<shared:TabControlEx Grid.Row="0"
|
||||||
|
ItemsSource="{Binding Editors}"
|
||||||
SelectedItem="{Binding SelectedEditor}"
|
SelectedItem="{Binding SelectedEditor}"
|
||||||
AddTabCommand="{Binding AddEditorCommand}"
|
AddTabCommand="{Binding AddEditorCommand}"
|
||||||
AutoScrollToEnd="{Binding AutoSelectNewEditor}">
|
AutoScrollToEnd="{Binding AutoSelectNewEditor}">
|
||||||
@@ -70,7 +77,110 @@
|
|||||||
</shared:TabControlEx.ItemContainerStyle>
|
</shared:TabControlEx.ItemContainerStyle>
|
||||||
</shared:TabControlEx>
|
</shared:TabControlEx>
|
||||||
|
|
||||||
<Expander Header="Click to hide/show"
|
<!-- Log Panel -->
|
||||||
|
<Border Grid.Row="1" Height="3" Cursor="SizeNS"
|
||||||
|
Background="Transparent">
|
||||||
|
<Border.Style>
|
||||||
|
<Style TargetType="Border">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding LogPanel.IsOpen}" Value="False">
|
||||||
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Border.Style>
|
||||||
|
<GridSplitter HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Background="#FF3F3F46"
|
||||||
|
ResizeBehavior="PreviousAndNext"
|
||||||
|
ResizeDirection="Rows" />
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Border Grid.Row="2" Background="#FF1E1E1E" BorderBrush="#FF3F3F46" BorderThickness="0,1,0,0">
|
||||||
|
<Border.Style>
|
||||||
|
<Style TargetType="Border">
|
||||||
|
<Setter Property="Height" Value="180" />
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding LogPanel.IsOpen}" Value="False">
|
||||||
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
|
<Setter Property="Height" Value="0" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</Border.Style>
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="28" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- Header bar -->
|
||||||
|
<Border Grid.Row="0" Background="#FF2D2D30" BorderBrush="#FF3F3F46" BorderThickness="0,0,0,1">
|
||||||
|
<DockPanel Margin="8,0">
|
||||||
|
<TextBlock Text="⚡ Output" VerticalAlignment="Center" Foreground="#FFDCDCDC" FontWeight="SemiBold" FontSize="12" />
|
||||||
|
<TextBlock VerticalAlignment="Center" Margin="10,0,0,0" Foreground="#FF888888" FontSize="11">
|
||||||
|
<TextBlock.Style>
|
||||||
|
<Style TargetType="TextBlock">
|
||||||
|
<Setter Property="Text" Value="" />
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding LogPanel.IsRunning}" Value="True">
|
||||||
|
<Setter Property="Text" Value="● Running..." />
|
||||||
|
<Setter Property="Foreground" Value="#FF4EC9B0" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TextBlock.Style>
|
||||||
|
</TextBlock>
|
||||||
|
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||||
|
<Button Content="🗑 Clear" Command="{Binding LogPanel.ClearLogsCommand}"
|
||||||
|
Background="Transparent" Foreground="#FFAAAAAA" BorderThickness="0"
|
||||||
|
Padding="6,2" FontSize="11" Cursor="Hand" Margin="0,0,4,0" />
|
||||||
|
<Button Content="✕" Command="{Binding LogPanel.ClosePanelCommand}"
|
||||||
|
Background="Transparent" Foreground="#FFAAAAAA" BorderThickness="0"
|
||||||
|
Padding="6,2" FontSize="11" Cursor="Hand" />
|
||||||
|
</StackPanel>
|
||||||
|
</DockPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Log entries -->
|
||||||
|
<ListBox Grid.Row="1" x:Name="LogListBox"
|
||||||
|
ItemsSource="{Binding LogPanel.LogEntries}"
|
||||||
|
Background="#FF1E1E1E" BorderThickness="0"
|
||||||
|
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||||
|
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||||
|
VirtualizingStackPanel.IsVirtualizing="True"
|
||||||
|
FontFamily="Consolas" FontSize="12">
|
||||||
|
<ListBox.ItemContainerStyle>
|
||||||
|
<Style TargetType="ListBoxItem">
|
||||||
|
<Setter Property="Padding" Value="8,1" />
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<Setter Property="BorderThickness" Value="0" />
|
||||||
|
<Setter Property="Focusable" Value="False" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="ListBoxItem">
|
||||||
|
<Border Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}">
|
||||||
|
<ContentPresenter />
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</ListBox.ItemContainerStyle>
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock TextWrapping="NoWrap">
|
||||||
|
<Run Text="{Binding Timestamp, Mode=OneTime}" Foreground="#FF608B4E" />
|
||||||
|
<Run Text=" " />
|
||||||
|
<Run Text="{Binding Message, Mode=OneTime}" Foreground="{Binding Color, Mode=OneTime}" />
|
||||||
|
</TextBlock>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Expander Grid.Row="0" Header="Click to hide/show"
|
||||||
IsExpanded="False"
|
IsExpanded="False"
|
||||||
Margin="10"
|
Margin="10"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using Nodify.Interactivity;
|
using Nodify.Interactivity;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
namespace Nodify.Calculator
|
namespace Nodify.Calculator
|
||||||
@@ -20,6 +22,23 @@ namespace Nodify.Calculator
|
|||||||
(KeyboardFocusChangedEventHandler)OnPreviewGotKeyboardFocus);
|
(KeyboardFocusChangedEventHandler)OnPreviewGotKeyboardFocus);
|
||||||
|
|
||||||
Closing += MainWindow_Closing;
|
Closing += MainWindow_Closing;
|
||||||
|
|
||||||
|
// Auto-scroll log list to bottom when new entries are added
|
||||||
|
Loaded += (_, __) =>
|
||||||
|
{
|
||||||
|
if (DataContext is ApplicationViewModel appVm)
|
||||||
|
{
|
||||||
|
((INotifyCollectionChanged)appVm.LogPanel.LogEntries).CollectionChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||||
|
{
|
||||||
|
var listBox = FindName("LogListBox") as ListBox;
|
||||||
|
if (listBox != null && appVm.LogPanel.LogEntries.Count > 0)
|
||||||
|
listBox.ScrollIntoView(appVm.LogPanel.LogEntries[appVm.LogPanel.LogEntries.Count - 1]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MainWindow_Closing(object sender, CancelEventArgs e)
|
private void MainWindow_Closing(object sender, CancelEventArgs e)
|
||||||
|
|||||||
Reference in New Issue
Block a user