mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 04:18:43 +00:00
Builder improvements.
This commit is contained in:
parent
e10351dcd2
commit
d2dec6e316
7 changed files with 143 additions and 204 deletions
|
|
@ -13,8 +13,9 @@ namespace Cosmos.Build.Builder
|
|||
{
|
||||
if (e.Args.Length == 0)
|
||||
{
|
||||
MessageBox.Show("Builder not meant to be called directly. Use install-VS2017.bat instead.");
|
||||
ShowErrorMessageBox("Builder not meant to be called directly. Use install-VS2017.bat instead.");
|
||||
Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
var configuration = new CommandLineBuilderConfiguration(e.Args);
|
||||
|
|
@ -31,13 +32,17 @@ namespace Cosmos.Build.Builder
|
|||
// For debugging, set params to something like this:
|
||||
// -VSPath=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise
|
||||
|
||||
MessageBox.Show("Visual Studio path must be provided. (-VSPATH or /VSPATH)");
|
||||
ShowErrorMessageBox("Visual Studio path must be provided. (-VSPATH or /VSPATH)");
|
||||
Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
BuilderConfiguration = configuration;
|
||||
|
||||
base.OnStartup(e);
|
||||
}
|
||||
|
||||
private void ShowErrorMessageBox(string message) =>
|
||||
MessageBox.Show(message, "Cosmos Kit Builder", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
using Cosmos.Build.Builder.Models;
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
using Cosmos.Build.Builder.Models;
|
||||
|
||||
namespace Cosmos.Build.Builder.ViewModels
|
||||
{
|
||||
internal class MainWindowLogger : ILogger
|
||||
{
|
||||
private static readonly string[] NewLineStringArray = new string[] { Environment.NewLine };
|
||||
|
||||
private readonly MainWindowViewModel _viewModel;
|
||||
|
||||
public MainWindowLogger(MainWindowViewModel viewModel)
|
||||
|
|
@ -11,21 +16,29 @@ namespace Cosmos.Build.Builder.ViewModels
|
|||
_viewModel = viewModel;
|
||||
}
|
||||
|
||||
public void LogMessage(string text)
|
||||
{
|
||||
_viewModel.CurrentSection.LogMessage(text);
|
||||
_viewModel.TailItems.Push(text);
|
||||
}
|
||||
public void LogMessage(string text) => Application.Current.Dispatcher.Invoke(
|
||||
() =>
|
||||
{
|
||||
_viewModel.CurrentSection.LogMessage(text);
|
||||
|
||||
public void NewSection(string name)
|
||||
{
|
||||
_viewModel.Sections.Add(new Section(name));
|
||||
_viewModel.TailItems.Clear();
|
||||
}
|
||||
foreach (var line in text.Split(NewLineStringArray, StringSplitOptions.None))
|
||||
{
|
||||
_viewModel.TailItems.Push(line);
|
||||
}
|
||||
});
|
||||
|
||||
public void SetError()
|
||||
{
|
||||
_viewModel.CurrentSection.SetError();
|
||||
}
|
||||
public void NewSection(string name) => Application.Current.Dispatcher.Invoke(
|
||||
() =>
|
||||
{
|
||||
_viewModel.Sections.Add(new Section(name));
|
||||
_viewModel.TailItems.Clear();
|
||||
});
|
||||
|
||||
public void SetError() => Application.Current.Dispatcher.Invoke(
|
||||
() =>
|
||||
{
|
||||
_viewModel.CurrentSection.SetError();
|
||||
_viewModel.CloseWhenCompleted = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
using Cosmos.Build.Builder.Collections;
|
||||
using Cosmos.Build.Builder.Models;
|
||||
|
||||
namespace Cosmos.Build.Builder.ViewModels
|
||||
{
|
||||
internal class MainWindowViewModel
|
||||
internal class MainWindowViewModel : ViewModelBase
|
||||
{
|
||||
private const int ReleaseNumber = 106027;
|
||||
|
||||
private const int TailItemCount = 10;
|
||||
|
||||
public ObservableFixedSizeStack<string> TailItems { get; }
|
||||
|
|
@ -20,19 +23,38 @@ namespace Cosmos.Build.Builder.ViewModels
|
|||
|
||||
public ICommand CopyCommand { get; }
|
||||
|
||||
private ILogger _logger;
|
||||
public bool CloseWhenCompleted
|
||||
{
|
||||
get => _closeWhenCompleted;
|
||||
set => SetAndRaiseIfChanged(ref _closeWhenCompleted, value);
|
||||
}
|
||||
|
||||
private CosmosTask _cosmosTask;
|
||||
private Task _cosmosTaskTask;
|
||||
|
||||
private bool _closeWhenCompleted;
|
||||
|
||||
public MainWindowViewModel()
|
||||
{
|
||||
TailItems = new ObservableFixedSizeStack<string>(TailItemCount);
|
||||
Sections = new ObservableCollection<Section>();
|
||||
|
||||
CopyCommand = new CopyLogCommand(this);
|
||||
CopyCommand = new RelayCommand(CopyLogToClipboard);
|
||||
|
||||
_logger = new MainWindowLogger(this);
|
||||
var logger = new MainWindowLogger(this);
|
||||
|
||||
_closeWhenCompleted = true;
|
||||
|
||||
var cosmosDir = Directory.GetCurrentDirectory();
|
||||
|
||||
_cosmosTask = new CosmosTask(logger, cosmosDir, ReleaseNumber);
|
||||
_cosmosTaskTask = Task.Run((Action)_cosmosTask.Run);
|
||||
_cosmosTaskTask.ContinueWith(CosmosTaskFinishedAsync);
|
||||
}
|
||||
|
||||
public string BuildLog()
|
||||
private void CopyLogToClipboard(object parameter) => Clipboard.SetText(BuildLog());
|
||||
|
||||
private string BuildLog()
|
||||
{
|
||||
var log = @"
|
||||
========================================
|
||||
|
|
@ -55,23 +77,25 @@ namespace Cosmos.Build.Builder.ViewModels
|
|||
return log;
|
||||
}
|
||||
|
||||
private class CopyLogCommand : ICommand
|
||||
{
|
||||
public event EventHandler CanExecuteChanged;
|
||||
private Task CosmosTaskFinishedAsync(Task task) =>
|
||||
Application.Current.Dispatcher.InvokeAsync(
|
||||
async () =>
|
||||
{
|
||||
var mainWindow = Application.Current.MainWindow;
|
||||
|
||||
private MainWindowViewModel _viewModel;
|
||||
private Func<bool> _canExecute;
|
||||
await Task.Delay(5000);
|
||||
|
||||
public CopyLogCommand(MainWindowViewModel viewModel, Func<bool> canExecute = null)
|
||||
{
|
||||
_viewModel = viewModel;
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public bool CanExecute(object parameter) => _canExecute?.Invoke() ?? true;
|
||||
public void Execute(object parameter) => Clipboard.SetText(_viewModel.BuildLog());
|
||||
|
||||
public void RaiseCanExecuteChanged(object sender, EventArgs e) => CanExecuteChanged?.Invoke(sender, e);
|
||||
}
|
||||
if (CloseWhenCompleted)
|
||||
{
|
||||
mainWindow.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mainWindow.WindowState == WindowState.Maximized)
|
||||
{
|
||||
mainWindow.WindowState = WindowState.Normal;
|
||||
}
|
||||
}
|
||||
}).Task;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
24
source/Cosmos.Build.Builder/ViewModels/RelayCommand.cs
Normal file
24
source/Cosmos.Build.Builder/ViewModels/RelayCommand.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Cosmos.Build.Builder.ViewModels
|
||||
{
|
||||
internal class RelayCommand : ICommand
|
||||
{
|
||||
public event EventHandler CanExecuteChanged;
|
||||
|
||||
private Action<object> _execute;
|
||||
private Func<object, bool> _canExecute;
|
||||
|
||||
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
|
||||
{
|
||||
_execute = execute;
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public bool CanExecute(object parameter) => _canExecute?.Invoke(parameter) ?? true;
|
||||
public void Execute(object parameter) => _execute?.Invoke(parameter);
|
||||
|
||||
public void RaiseCanExecuteChanged(object sender, EventArgs e) => CanExecuteChanged?.Invoke(sender, e);
|
||||
}
|
||||
}
|
||||
23
source/Cosmos.Build.Builder/ViewModels/ViewModelBase.cs
Normal file
23
source/Cosmos.Build.Builder/ViewModels/ViewModelBase.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Cosmos.Build.Builder.ViewModels
|
||||
{
|
||||
internal abstract class ViewModelBase : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected void SetAndRaiseIfChanged<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (!EqualityComparer<T>.Default.Equals(field, value))
|
||||
{
|
||||
field = value;
|
||||
OnPropertyChanged(propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnPropertyChanged([CallerMemberName] string propertyName = null) =>
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
|
@ -5,10 +5,8 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Icon="/Cosmos.Build.Builder;component/Resources/Cosmos.ico"
|
||||
Loaded="Window_Loaded"
|
||||
MinHeight="480"
|
||||
MinWidth="800"
|
||||
SizeChanged="Window_SizeChanged"
|
||||
Title="Cosmos Kit Builder"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
DataContext="{StaticResource MainWindowViewModel}">
|
||||
|
|
@ -18,10 +16,21 @@
|
|||
|
||||
<DockPanel>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Top">
|
||||
<Button Command="{Binding CopyCommand}"
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Grid.Column="0"
|
||||
Command="{Binding CopyCommand}"
|
||||
Content="Copy" />
|
||||
</WrapPanel>
|
||||
|
||||
<CheckBox Grid.Column="2"
|
||||
IsChecked="{Binding CloseWhenCompleted}"
|
||||
Content="Close window when completed" />
|
||||
</Grid>
|
||||
|
||||
<Rectangle DockPanel.Dock="Top"
|
||||
Height="5" />
|
||||
|
|
|
|||
|
|
@ -1,171 +1,12 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
using Cosmos.Build.Builder.Models;
|
||||
using Cosmos.Build.Installer;
|
||||
using System.Windows;
|
||||
|
||||
namespace Cosmos.Build.Builder.Views
|
||||
{
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private static readonly string[] NewLineStringArray = new string[] { Environment.NewLine };
|
||||
|
||||
string mCosmosDir;
|
||||
string mSetupPath;
|
||||
// Needs updating with each new release.
|
||||
int mReleaseNo = 106027;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
bool mPreventAutoClose = false;
|
||||
StringBuilder mClipboard = new StringBuilder();
|
||||
DispatcherTimer mCloseTimer;
|
||||
|
||||
public bool Build()
|
||||
{
|
||||
Log.LogLine += new Log.LogLineHandler(Log_LogLine);
|
||||
Log.LogSection += new Log.LogSectionHandler(Log_LogSection);
|
||||
Log.LogError += new Log.LogErrorHandler(Log_LogError);
|
||||
|
||||
if (App.BuilderConfiguration.UserKit)
|
||||
{
|
||||
mReleaseNo = Int32.Parse(DateTime.Now.ToString("yyyyMMdd"));
|
||||
}
|
||||
if (mPreventAutoClose)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var xTask = new CosmosTask(mCosmosDir, mReleaseNo);
|
||||
|
||||
var xThread = new System.Threading.Thread(delegate ()
|
||||
{
|
||||
xTask.Run();
|
||||
ThreadDone();
|
||||
});
|
||||
xThread.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ThreadDone()
|
||||
{
|
||||
Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate ()
|
||||
{
|
||||
if (App.BuilderConfiguration.StayOpen == false)
|
||||
{
|
||||
mCloseTimer = new DispatcherTimer();
|
||||
mCloseTimer.Interval = TimeSpan.FromSeconds(5);
|
||||
mCloseTimer.Tick += delegate
|
||||
{
|
||||
mCloseTimer.Stop();
|
||||
if (mPreventAutoClose)
|
||||
{
|
||||
if (WindowState == WindowState.Minimized)
|
||||
{
|
||||
WindowState = WindowState.Normal;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
}
|
||||
};
|
||||
mCloseTimer.Start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ClearTail() => DoOnViewModel(vm => vm.TailItems.Clear());
|
||||
|
||||
void Log_LogError()
|
||||
{
|
||||
Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate ()
|
||||
{
|
||||
ClearTail();
|
||||
|
||||
DoOnViewModel(vm => vm.CurrentSection?.SetError());
|
||||
|
||||
mPreventAutoClose = true;
|
||||
});
|
||||
}
|
||||
|
||||
void Log_LogLine(string aLine)
|
||||
{
|
||||
Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate ()
|
||||
{
|
||||
WriteTail(aLine);
|
||||
|
||||
DoOnViewModel(vm => vm.CurrentSection?.LogMessage(aLine));
|
||||
|
||||
mClipboard.AppendLine(aLine);
|
||||
});
|
||||
}
|
||||
|
||||
void Log_LogSection(string name)
|
||||
{
|
||||
Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate ()
|
||||
{
|
||||
DoOnViewModel(vm => vm.Sections.Add(new Section(name)));
|
||||
|
||||
ClearTail();
|
||||
|
||||
mClipboard.AppendLine();
|
||||
mClipboard.AppendLine(new string('=', name.Length));
|
||||
mClipboard.AppendLine(name);
|
||||
mClipboard.AppendLine(new string('=', name.Length));
|
||||
mClipboard.AppendLine();
|
||||
});
|
||||
}
|
||||
|
||||
void WriteTail(string aText) => DoOnViewModel(
|
||||
vm =>
|
||||
{
|
||||
foreach (var line in aText.Split(NewLineStringArray, StringSplitOptions.None))
|
||||
{
|
||||
vm.TailItems.Push(line);
|
||||
}
|
||||
});
|
||||
|
||||
protected bool mLoaded = false;
|
||||
void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
mLoaded = true;
|
||||
|
||||
DoOnViewModel(vm => vm.LogBuilder = mClipboard);
|
||||
|
||||
string xAppPath = AppContext.BaseDirectory;
|
||||
mCosmosDir = Path.GetFullPath(xAppPath + @"..\..\..\..\..\");
|
||||
mSetupPath = Path.Combine(mCosmosDir, @"Setup\Output\" + CosmosTask.GetSetupName(mReleaseNo) + ".exe");
|
||||
if (!Build())
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
// User had non minimized window, or maximized it, or otherwise manually intervened.
|
||||
// Even if starting minimized, this event gets called with Normal before load.
|
||||
// This is why we have mLoaded.
|
||||
if (mLoaded && WindowState != WindowState.Minimized)
|
||||
{
|
||||
mPreventAutoClose = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void DoOnViewModel(Action<ViewModels.MainWindowViewModel> action)
|
||||
{
|
||||
if (DataContext is ViewModels.MainWindowViewModel viewModel)
|
||||
{
|
||||
action(viewModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue