diff --git a/VECTO3GUI/App.config b/VECTO3GUI/App.config index 3d1145dfc2695645de184f2dcd268328d918b0c1..43a59994b753ba74a4a681fe158167c841fdcbf8 100644 --- a/VECTO3GUI/App.config +++ b/VECTO3GUI/App.config @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> - <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > + <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <section name="VECTO3GUI.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" /> </sectionGroup> </configSections> diff --git a/VECTO3GUI/Helper/Converter/JobEntrySelectedConverter.cs b/VECTO3GUI/Helper/Converter/JobEntrySelectedConverter.cs index e34b9b0f0693c7467e52640138414e004662b1fe..8e80432b9d017e47fd0b9c0637ff6132f6d146d6 100644 --- a/VECTO3GUI/Helper/Converter/JobEntrySelectedConverter.cs +++ b/VECTO3GUI/Helper/Converter/JobEntrySelectedConverter.cs @@ -11,8 +11,9 @@ namespace VECTO3GUI.Helper.Converter public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - var jobEntry = (ViewModel.Impl.JobEntry)((ListViewItem)value)?.Content; - return jobEntry != null && jobEntry.Selected; + //var jobEntry = (ViewModel.Impl.JobEntry)((ListViewItem)value)?.Content; + //return jobEntry != null && jobEntry.Selected; + return value; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) diff --git a/VECTO3GUI/Helper/EventCommandExecuter.cs b/VECTO3GUI/Helper/EventCommandExecuter.cs new file mode 100644 index 0000000000000000000000000000000000000000..7457f06bff79d101835d2c8404d349131bd95599 --- /dev/null +++ b/VECTO3GUI/Helper/EventCommandExecuter.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Windows; +using System.Windows.Data; +using System.Windows.Input; +using System.Windows.Interactivity; + +namespace VECTO3GUI.Helper +{ + public class EventCommandExecuter : TriggerAction<DependencyObject> + { + #region Constructors + + public EventCommandExecuter() + : this(CultureInfo.CurrentCulture) + { + } + + public EventCommandExecuter(CultureInfo culture) + { + Culture = culture; + } + + #endregion + + #region Properties + + #region Command + + public ICommand Command + { + get { return (ICommand)GetValue(CommandProperty); } + set { SetValue(CommandProperty, value); } + } + + public static readonly DependencyProperty CommandProperty = + DependencyProperty.Register(nameof(Command), typeof(ICommand), typeof(EventCommandExecuter), new PropertyMetadata(null)); + + #endregion + + #region EventArgsConverterParameter + + public object EventArgsConverterParameter + { + get { return (object)GetValue(EventArgsConverterParameterProperty); } + set { SetValue(EventArgsConverterParameterProperty, value); } + } + + public static readonly DependencyProperty EventArgsConverterParameterProperty = + DependencyProperty.Register(nameof(EventArgsConverterParameter), typeof(object), typeof(EventCommandExecuter), new PropertyMetadata(null)); + + #endregion + + public IValueConverter EventArgsConverter { get; set; } + + public CultureInfo Culture { get; set; } + + #endregion + + protected override void Invoke(object parameter) + { + var cmd = Command; + + if (cmd != null) + { + var param = parameter; + + if (EventArgsConverter != null) + { + param = EventArgsConverter.Convert(parameter, typeof(object), EventArgsConverterParameter, CultureInfo.InvariantCulture); + } + + if (cmd.CanExecute(param)) + { + cmd.Execute(param); + } + } + } + } +} diff --git a/VECTO3GUI/Helper/Extension.cs b/VECTO3GUI/Helper/Extension.cs index 5481aa798cb10ced9325780fb4822adbca67bad2..7e3ebb2e02b3cc2b08d52cf59416f4bead23693f 100644 --- a/VECTO3GUI/Helper/Extension.cs +++ b/VECTO3GUI/Helper/Extension.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; namespace VECTO3GUI.Helper { @@ -29,5 +31,29 @@ namespace VECTO3GUI.Helper return currentObj; } + + public static XmlDocument ToXmlDocument(this XDocument xDocument) + { + var xmlDocument = new XmlDocument(); + using (var reader = xDocument.CreateReader()) + { + xmlDocument.Load(reader); + } + + var xDeclaration = xDocument.Declaration; + if (xDeclaration != null) + { + var xmlDeclaration = xmlDocument.CreateXmlDeclaration( + xDeclaration.Version, + xDeclaration.Encoding, + xDeclaration.Standalone); + + xmlDocument.InsertBefore(xmlDeclaration, xmlDocument.FirstChild); + } + + return xmlDocument; + } + + } } diff --git a/VECTO3GUI/Helper/FileDialogHelper.cs b/VECTO3GUI/Helper/FileDialogHelper.cs index 8baf328f121cb10fb52c8e67c7e5eb8860b7c97a..e8bfe59e80d6798c8db1502f09c8672edabbba55 100644 --- a/VECTO3GUI/Helper/FileDialogHelper.cs +++ b/VECTO3GUI/Helper/FileDialogHelper.cs @@ -13,16 +13,21 @@ namespace VECTO3GUI.Helper { public static class FileDialogHelper { - private const string XMLFilter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*"; + public const string XMLFilter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*"; + public const string JobFilter = "Job Files (*.vectojob|*.vectojob|All Files (*.*)|*.*"; - - public static string[] ShowSelectFilesDialog(bool multiselect, string initialDirectory = null) + public static string[] ShowSelectFilesDialog(bool multiselect) + { + return ShowSelectFilesDialog(multiselect, XMLFilter); + } + + public static string[] ShowSelectFilesDialog(bool multiselect, string filter = XMLFilter, string initialDirectory = null) { using (var openFileDialog = new OpenFileDialog()) { openFileDialog.InitialDirectory = initialDirectory; openFileDialog.Multiselect = multiselect; - openFileDialog.Filter = XMLFilter; + openFileDialog.Filter = filter; var result = openFileDialog.ShowDialog(); if (result == DialogResult.OK) @@ -33,8 +38,7 @@ namespace VECTO3GUI.Helper return null; } - - + public static string ShowSelectDirectoryDialog(string initialDirectory = null) { using (var dialog = new CommonOpenFileDialog()) @@ -52,6 +56,27 @@ namespace VECTO3GUI.Helper return null; } + public static string SaveXmlFileToDialog(string initialDirectory = null) + { + return SaveToDialog(initialDirectory, XMLFilter); + } + public static string SaveJobFileToDialog(string initialDirectory = null) + { + return SaveToDialog(initialDirectory, JobFilter); + } + + private static string SaveToDialog(string initialDirectory, string filter) + { + var saveFileDialog = new SaveFileDialog + { + Filter = filter + }; + + if (initialDirectory != null) + saveFileDialog.InitialDirectory = initialDirectory; + + return saveFileDialog.ShowDialog() == true ? saveFileDialog.FileName : null; + } } } diff --git a/VECTO3GUI/Helper/MetroDialogHelper.cs b/VECTO3GUI/Helper/MetroDialogHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..efcbcbf19c75b34080da9ff20950954f1740d767 --- /dev/null +++ b/VECTO3GUI/Helper/MetroDialogHelper.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MahApps.Metro.Controls.Dialogs; + +namespace VECTO3GUI.Helper +{ + public static class MetroDialogHelper + { + public static MessageDialogResult GetModalDialogBox(object viewModel, string title, string message, + MetroDialogSettings settings) + { + return GetModalDialogBox(viewModel, title, message, MessageDialogStyle.AffirmativeAndNegative, settings); + } + + public static MessageDialogResult GetModalDialogBox(object viewModel, string title, string message, + MessageDialogStyle style = MessageDialogStyle.AffirmativeAndNegative, MetroDialogSettings settings = null) + { + var coordinator = DialogCoordinator.Instance; + return coordinator.ShowModalMessageExternal(viewModel, title, message, style, settings); + } + } +} diff --git a/VECTO3GUI/Helper/ObservableCollectionEx.cs b/VECTO3GUI/Helper/ObservableCollectionEx.cs new file mode 100644 index 0000000000000000000000000000000000000000..6253bc2a4ae2af40edaf3fb305b0231165b250bc --- /dev/null +++ b/VECTO3GUI/Helper/ObservableCollectionEx.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using Castle.Core.Internal; + +namespace VECTO3GUI.Helper +{ + public class ObservableCollectionEx<T> : ObservableCollection<T> + { + public event PropertyChangedEventHandler CollectionItemChanged; + + public ObservableCollectionEx() + { + CollectionChanged += FullObservableCollectionCollectionChanged; + } + + public ObservableCollectionEx(IEnumerable<T> items) : this() + { + if (items == null) + return; + + foreach (var item in items) { + Add(item); + } + } + + public ObservableCollectionEx(IList<T> items) : this() + { + if(items.IsNullOrEmpty()) + return; + for (int i = 0; i < items.Count; i++) { + Add(items[i]); + } + } + + + private void FullObservableCollectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (e.NewItems != null) + { + foreach (object item in e.NewItems) + { + ((INotifyPropertyChanged)item).PropertyChanged += ItemPropertyChanged; + } + } + if (e.OldItems != null) + { + foreach (object item in e.OldItems) + { + ((INotifyPropertyChanged)item).PropertyChanged -= ItemPropertyChanged; + } + } + } + + private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e) + { + CollectionItemChanged?.Invoke(sender, e); + + var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, sender, sender, IndexOf((T)sender)); + OnCollectionChanged(args); + } + } +} diff --git a/VECTO3GUI/Helper/OutputWindowHelper.cs b/VECTO3GUI/Helper/OutputWindowHelper.cs index c7a7d13d60d6f22ce4067d1f5b22b993051e6165..cf43a30d34ee03d41559ba1abb27346b246c0127 100644 --- a/VECTO3GUI/Helper/OutputWindowHelper.cs +++ b/VECTO3GUI/Helper/OutputWindowHelper.cs @@ -19,7 +19,7 @@ namespace VECTO3GUI.Helper } public static OutputWindow CreateOutputWindow(IKernel kernel, object viewModel, - string windowName,double width = default(double), double height = default(double), + string windowName, double width = default(double), double height = default(double), ResizeMode resizeMode = ResizeMode.CanResize) { var window = CreateWindow(kernel, viewModel, windowName, width, height); diff --git a/VECTO3GUI/Helper/SerializeHelper.cs b/VECTO3GUI/Helper/SerializeHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..fea12d4803612c114efe7b2035a3b9a0ec335542 --- /dev/null +++ b/VECTO3GUI/Helper/SerializeHelper.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Castle.Core.Internal; +using Newtonsoft.Json; + +namespace VECTO3GUI.Helper +{ + public static class SerializeHelper + { + public static void SerializeToFile<T>(string filePath, T file) + { + if (filePath.IsNullOrEmpty() || file == null) + return; + + var serializedObject = JsonConvert.SerializeObject(file, Formatting.Indented); + File.WriteAllText(filePath, serializedObject); + } + + public static T DeserializeToObject<T>(string filePath) + { + if (filePath.IsNullOrEmpty()) + return default(T); + + using (var file = File.OpenText(filePath)) { + var serializer = new JsonSerializer(); + var result = serializer.Deserialize(file,typeof(T)); + if (result == null) + return default(T); + + return (T)result; + } + } + + } +} diff --git a/VECTO3GUI/Helper/TextBoxInputRegExBehaviour.cs b/VECTO3GUI/Helper/TextBoxInputRegExBehaviour.cs new file mode 100644 index 0000000000000000000000000000000000000000..b8aeb35952676b0292c4f01fe1503688f4853b9f --- /dev/null +++ b/VECTO3GUI/Helper/TextBoxInputRegExBehaviour.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Interactivity; + +namespace VECTO3GUI.Helper +{ + /// Taken from https://stackoverflow.com/a/17715402 + /// <summary> + /// Regular expression for Textbox with properties: + /// <see cref="RegularExpression"/>, + /// <see cref="MaxLength"/>, + /// <see cref="EmptyValue"/>. + /// </summary> + public class TextBoxInputRegExBehaviour : Behavior<TextBox> + { + #region DependencyProperties + public static readonly DependencyProperty RegularExpressionProperty = + DependencyProperty.Register("RegularExpression", typeof(string), typeof(TextBoxInputRegExBehaviour), new FrameworkPropertyMetadata(".*")); + + public string RegularExpression + { + get { return (string)GetValue(RegularExpressionProperty); } + set { SetValue(RegularExpressionProperty, value); } + } + + public static readonly DependencyProperty MaxLengthProperty = + DependencyProperty.Register("MaxLength", typeof(int), typeof(TextBoxInputRegExBehaviour), + new FrameworkPropertyMetadata(int.MinValue)); + + public int MaxLength + { + get { return (int)GetValue(MaxLengthProperty); } + set { SetValue(MaxLengthProperty, value); } + } + + public static readonly DependencyProperty EmptyValueProperty = + DependencyProperty.Register("EmptyValue", typeof(string), typeof(TextBoxInputRegExBehaviour), null); + + public string EmptyValue + { + get { return (string)GetValue(EmptyValueProperty); } + set { SetValue(EmptyValueProperty, value); } + } + #endregion + + /// <summary> + /// Attach our behaviour. Add event handlers + /// </summary> + protected override void OnAttached() + { + base.OnAttached(); + + AssociatedObject.PreviewTextInput += PreviewTextInputHandler; + AssociatedObject.PreviewKeyDown += PreviewKeyDownHandler; + DataObject.AddPastingHandler(AssociatedObject, PastingHandler); + } + + /// <summary> + /// Deattach our behaviour. remove event handlers + /// </summary> + protected override void OnDetaching() + { + base.OnDetaching(); + + AssociatedObject.PreviewTextInput -= PreviewTextInputHandler; + AssociatedObject.PreviewKeyDown -= PreviewKeyDownHandler; + DataObject.RemovePastingHandler(AssociatedObject, PastingHandler); + } + + #region Event handlers [PRIVATE] -------------------------------------- + + void PreviewTextInputHandler(object sender, TextCompositionEventArgs e) + { + string text; + if (this.AssociatedObject.Text.Length < this.AssociatedObject.CaretIndex) + text = this.AssociatedObject.Text; + else + { + // Remaining text after removing selected text. + string remainingTextAfterRemoveSelection; + + text = TreatSelectedText(out remainingTextAfterRemoveSelection) + ? remainingTextAfterRemoveSelection.Insert(AssociatedObject.SelectionStart, e.Text) + : AssociatedObject.Text.Insert(this.AssociatedObject.CaretIndex, e.Text); + } + + e.Handled = !ValidateText(text); + } + + /// <summary> + /// PreviewKeyDown event handler + /// </summary> + void PreviewKeyDownHandler(object sender, KeyEventArgs e) + { + if (string.IsNullOrEmpty(this.EmptyValue)) + return; + + string text = null; + + // Handle the Backspace key + if (e.Key == Key.Back) + { + if (!this.TreatSelectedText(out text)) + { + if (AssociatedObject.SelectionStart > 0) + text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart - 1, 1); + } + } + // Handle the Delete key + else if (e.Key == Key.Delete) + { + // If text was selected, delete it + if (!this.TreatSelectedText(out text) && this.AssociatedObject.Text.Length > AssociatedObject.SelectionStart) + { + // Otherwise delete next symbol + text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart, 1); + } + } + + if (text == string.Empty) + { + this.AssociatedObject.Text = this.EmptyValue; + if (e.Key == Key.Back) + AssociatedObject.SelectionStart++; + e.Handled = true; + } + } + + private void PastingHandler(object sender, DataObjectPastingEventArgs e) + { + if (e.DataObject.GetDataPresent(DataFormats.Text)) + { + string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text)); + + if (!ValidateText(text)) + e.CancelCommand(); + } + else + e.CancelCommand(); + } + #endregion Event handlers [PRIVATE] ----------------------------------- + + #region Auxiliary methods [PRIVATE] ----------------------------------- + + /// <summary> + /// Validate certain text by our regular expression and text length conditions + /// </summary> + /// <param name="text"> Text for validation </param> + /// <returns> True - valid, False - invalid </returns> + private bool ValidateText(string text) + { + return (new Regex(this.RegularExpression, RegexOptions.IgnoreCase)).IsMatch(text) && (MaxLength == int.MinValue || text.Length <= MaxLength); + } + + /// <summary> + /// Handle text selection + /// </summary> + /// <returns>true if the character was successfully removed; otherwise, false. </returns> + private bool TreatSelectedText(out string text) + { + text = null; + if (AssociatedObject.SelectionLength <= 0) + return false; + + var length = this.AssociatedObject.Text.Length; + if (AssociatedObject.SelectionStart >= length) + return true; + + if (AssociatedObject.SelectionStart + AssociatedObject.SelectionLength >= length) + AssociatedObject.SelectionLength = length - AssociatedObject.SelectionStart; + + text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart, AssociatedObject.SelectionLength); + return true; + } + #endregion Auxiliary methods [PRIVATE] -------------------------------- + } +} + diff --git a/VECTO3GUI/Helper/ViewModelBase.cs b/VECTO3GUI/Helper/ViewModelBase.cs new file mode 100644 index 0000000000000000000000000000000000000000..2ed110649bd797cc4eeef4837324b36113faceb7 --- /dev/null +++ b/VECTO3GUI/Helper/ViewModelBase.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using Castle.Core.Internal; +using VECTO3GUI.ViewModel.Impl; + +namespace VECTO3GUI.Helper +{ + public class ViewModelBase : ObservableObject, INotifyDataErrorInfo + { + + private readonly Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>(); + public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; + + public IEnumerable GetErrors(string propertyName) + { + if (propertyName.IsNullOrEmpty()) + return null; + + return _errors.ContainsKey(propertyName) ? _errors[propertyName] : null; + } + + public bool HasErrors + { + get + { + return _errors.Count > 0; + } + } + + public bool IsValid + { + get + { + return !HasErrors; + } + } + + public void AddPropertyError(string propertyName, string error) + { + if (_errors.ContainsKey(propertyName)) + _errors[propertyName].Add(error); + else + _errors[propertyName] = new List<string>() { error }; + + NotifyErrorsChanged(propertyName); + } + + public void RemovePropertyError(string propertyName) + { + if (_errors.ContainsKey(propertyName)) + _errors.Remove(propertyName); + + NotifyErrorsChanged(propertyName); + } + + public void NotifyErrorsChanged(string propertyName) + { + ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName)); + } + } +} diff --git a/VECTO3GUI/Helper/XmlComponentReaderHelper.cs b/VECTO3GUI/Helper/XmlComponentReaderHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..5f614614186835409f6370616863ebf9a468af85 --- /dev/null +++ b/VECTO3GUI/Helper/XmlComponentReaderHelper.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Resources; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.InputData.FileIO.XML.Common; +using VECTO3GUI.Model.TempDataObject; + +namespace VECTO3GUI.Helper +{ + public class XmlComponentReaderHelper : AbstractXMLType + { + public XmlComponentReaderHelper(XmlNode node) : base(node) { } + + public AirdragComponentData GetAirdragComponentData() + { + if (!ElementExists(XMLNames.Component_AirDrag)) + return null; + + return new AirdragComponentData { + Manufacturer = GetString(XMLNames.Component_Manufacturer), + Model = GetString(XMLNames.Component_Model), + CertificationNumber = GetString(XMLNames.Component_CertificationNumber), + Date = DateTime.Parse(GetString(XMLNames.Component_Date)).ToUniversalTime(), + AppVersion = GetString(XMLNames.Component_AppVersion), + CdxA_0 = GetDouble("CdxA_0").SI<SquareMeter>(), + TransferredCdxA = GetDouble("TransferredCdxA").SI<SquareMeter>(), + DeclaredCdxA = GetDouble(XMLNames.AirDrag_DeclaredCdxA).SI<SquareMeter>(), + DigestValue = new DigestData(GetNode(XMLNames.DI_Signature)) + }; + } + } +} diff --git a/VECTO3GUI/Helper/XmlHelper.cs b/VECTO3GUI/Helper/XmlHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..e719f90c0fcde39764885193129658cf7795ad02 --- /dev/null +++ b/VECTO3GUI/Helper/XmlHelper.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; +using Castle.Core.Internal; +using Microsoft.WindowsAPICodePack.Shell.PropertySystem; +using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.Resources; +using TUGraz.VectoCore.Utils; + +namespace VECTO3GUI.Helper +{ + public static class XmlHelper + { + public static XmlDocument ReadXmlDocument(string filePath) + { + if (filePath.IsNullOrEmpty()) + return null; + + var xmlDocument = new XmlDocument(); + + using (var reader = new XmlTextReader(filePath)) { + xmlDocument.Load(reader); + } + + return xmlDocument; + } + + + public static XmlNodeList GetComponentNodes(XmlDocument xmlDocument, string parentNode, string nodeName) + { + if (xmlDocument == null || parentNode.IsNullOrEmpty() || nodeName.IsNullOrEmpty()) + return null; + + return xmlDocument.SelectNodes($"//*[local-name()='{parentNode}']//*[local-name()='{nodeName}']"); + } + + public static bool ValidateXDocument(XDocument xDocument) + { + var xmlDocument = xDocument.ToXmlDocument(); + if (xmlDocument == null) + return false; + + var documentType = XMLHelper.GetDocumentType(xmlDocument.DocumentElement.LocalName); + if (documentType == null) + { + throw new VectoException("unknown xml file! {0}", xmlDocument.DocumentElement.LocalName); + } + + var validator = new XMLValidator(xmlDocument, null, XMLValidator.CallBackExceptionOnError); + return validator.ValidateXML(documentType.Value); ; + } + } +} diff --git a/VECTO3GUI/MainWindow.xaml b/VECTO3GUI/MainWindow.xaml index 4f057ec99d45e6a6c0d4b589fa78058aa696f076..fccc5f76bc252becc04155f13d5441834090aa55 100644 --- a/VECTO3GUI/MainWindow.xaml +++ b/VECTO3GUI/MainWindow.xaml @@ -7,8 +7,10 @@ xmlns:interfaces="clr-namespace:VECTO3GUI.ViewModel.Interfaces" xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" xmlns:impl="clr-namespace:VECTO3GUI.ViewModel.Impl" + xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks" + xmlns:views="clr-namespace:VECTO3GUI.Views" mc:Ignorable="d" - Title="VECTO 3" Height="515.36" Width="972.48" WindowStartupLocation="CenterScreen" + Title="{Binding Version}" Height="515.36" Width="972.48" WindowStartupLocation="CenterScreen" d:DataContext="{d:DesignInstance Type=impl:MainWindowViewModel, IsDesignTimeCreatable=False}"> <Grid> @@ -22,28 +24,40 @@ <StackPanel Orientation="Vertical"> <Menu IsMainMenu="True" Style="{DynamicResource MetroMenu}"> - <MenuItem Header="File"> - <MenuItem Header="New" Style="{DynamicResource MetroMenuItem}" Margin="0" - Command="{Binding CurrentViewModel.CreateNewJob}"/> - <MenuItem Header="Edit" Style="{DynamicResource MetroMenuItem}" Margin="0" - Command="{Binding CurrentViewModel.EditJob}"/> - <Separator HorizontalAlignment="Stretch" Background="Gray"/> - <MenuItem Header="Open" Command="{Binding CurrentViewModel.AddJob}"/> - <MenuItem Header="Open Folder"/> + <MenuItem Header="File" VerticalAlignment="Center"> + + <MenuItem Header="Add Job" Command="{Binding CurrentViewModel.AddJob}"/> + <MenuItem Header="Edit Job" + Command="{Binding CurrentViewModel.EditJob}" + CommandParameter="{Binding CurrentViewModel.SelectedJobEntry}"/> + <MenuItem Header="Remove Job" + Command="{Binding CurrentViewModel.RemoveJob}" + CommandParameter="{Binding CurrentViewModel.SelectedJobEntry}"/> <Separator HorizontalAlignment="Stretch" Background="Gray"/> <MenuItem Header="Exit" Command="{Binding CurrentViewModel.ExitMainCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/> </MenuItem> - <MenuItem Header="Settings"> - <MenuItem Header="Default Settings" + + + <MenuItem Header="Tools" VerticalAlignment="Center"> + <!--<MenuItem.Icon> + <iconPacks:PackIconModern Width="15" Height="15" Kind="Tools" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Green" /> + </MenuItem.Icon>--> + <MenuItem Header="Create Single Bus Job" + Command="{Binding CurrentViewModel.AddBusJob}" CommandParameter="{Binding Source={x:Static impl:JobType.SingleBusJob}}"/> + <MenuItem Header="Create Completed Bus Job" + Command="{Binding CurrentViewModel.AddBusJob}" CommandParameter="{Binding Source={x:Static impl:JobType.CompletedBusJob}}"/> + <MenuItem Header="Create Completed XML" + Command="{Binding CurrentViewModel.CreateNewJob}"/> + <Separator HorizontalAlignment="Stretch" Background="Gray"/> + <MenuItem Header="Settings" Command="{Binding CurrentViewModel.OpenSettings}"/> </MenuItem> - <MenuItem Header="Help"> - <MenuItem Header="User Manual"/> + + <MenuItem Header="Help" VerticalAlignment="Center"> <MenuItem Header="About Vecto"/> - <MenuItem Header="Relase Notes"/> </MenuItem> </Menu> diff --git a/VECTO3GUI/Model/JobListModel.cs b/VECTO3GUI/Model/JobListModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..99a2fab3013dfbc539d3d496f2ce5e2c9e38aadc --- /dev/null +++ b/VECTO3GUI/Model/JobListModel.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Castle.Core.Internal; +using VECTO3GUI.Helper; +using VECTO3GUI.ViewModel.Impl; + +namespace VECTO3GUI.Model +{ + + public class JobListEntry + { + public bool IsSelected { get; set; } + public string JobFilePath { get; set; } + } + + public class JobListModel + { + private const string ConfigFolderName = "Config"; + private const string JobListFileName = "JobList.txt"; + + private string _jobListFilePath = Path.Combine(".", ConfigFolderName, JobListFileName); + + public List<JobListEntry> JobList { get; set; } + + public JobListModel() + { + SetConfigFolder(); + LoadJobList(); + } + + private void SetConfigFolder() + { + if (!Directory.Exists($"./{ConfigFolderName}")) { + Directory.CreateDirectory($"{ConfigFolderName}"); + } + } + + private void LoadJobList() + { + var jobList = new List<JobListEntry>(); + if (File.Exists(_jobListFilePath)) + jobList = SerializeHelper.DeserializeToObject<List<JobListEntry>>(_jobListFilePath); + JobList = jobList; + } + + + public void SaveJobList(IList<JobEntry> jobEntries) + { + SetJobList(jobEntries); + SerializeHelper.SerializeToFile(_jobListFilePath, JobList); + } + + private void SetJobList(IList<JobEntry> jobEntries) + { + if (jobEntries == null) + return; + + JobList = new List<JobListEntry>(); + + for (int i = 0; i < jobEntries.Count; i++) { + JobList.Add + ( + new JobListEntry + { + IsSelected = jobEntries[i].Selected, + JobFilePath = jobEntries[i].JobEntryFilePath + } + ); + } + } + + public IList<JobEntry> GetJobEntries() + { + var jobEntries = new List<JobEntry>(); + + if (JobList.IsNullOrEmpty()) + return jobEntries; + + for (int i = 0; i < JobList.Count; i++) { + var jobEntry = SerializeHelper.DeserializeToObject<JobEntry>(JobList[i].JobFilePath); + if(jobEntry != null) + jobEntries.Add(jobEntry); + } + + return jobEntries; + } + } +} diff --git a/VECTO3GUI/Model/TempDataObject/AirdragComponentData.cs b/VECTO3GUI/Model/TempDataObject/AirdragComponentData.cs index dc8b32e9caa64f99742b060b892077200f2532ec..ef0153e65d736811236018d35c77065a795e9680 100644 --- a/VECTO3GUI/Model/TempDataObject/AirdragComponentData.cs +++ b/VECTO3GUI/Model/TempDataObject/AirdragComponentData.cs @@ -27,6 +27,7 @@ namespace VECTO3GUI.Model.TempDataObject #endregion + public AirdragComponentData(){} public AirdragComponentData(IAirdragViewModel viewModel , bool defaultValues) { diff --git a/VECTO3GUI/Model/TempDataObject/AuxiliariesBusComponentData.cs b/VECTO3GUI/Model/TempDataObject/AuxiliariesBusComponentData.cs index 01324dfaf3e70631bcaae6e589539aa857c8d305..678c6f0b9bbfa1122ea5e910f7cbf670a989d5bc 100644 --- a/VECTO3GUI/Model/TempDataObject/AuxiliariesBusComponentData.cs +++ b/VECTO3GUI/Model/TempDataObject/AuxiliariesBusComponentData.cs @@ -28,6 +28,7 @@ namespace VECTO3GUI.Model.TempDataObject public bool HeatPump { get; set; } public bool AdjustableAuxiliaryHeater { get; set; } public bool SeparateAirDistributionDucts { get; set; } + public ConsumerTechnology DoorDriveTechnology { get; set; } #endregion @@ -63,6 +64,7 @@ namespace VECTO3GUI.Model.TempDataObject viewModel.HeatPump = HeatPump; viewModel.AdjustableAuxiliaryHeater = AdjustableAuxiliaryHeater; viewModel.SeparateAirDistributionDucts = SeparateAirDistributionDucts; + viewModel.DoorDriveTechnology = viewModel.DoorDriveTechnology; } public void ClearValues(IAuxiliariesViewModel viewModel) @@ -81,6 +83,7 @@ namespace VECTO3GUI.Model.TempDataObject viewModel.HeatPump = default(bool); viewModel.AdjustableAuxiliaryHeater = default(bool); viewModel.SeparateAirDistributionDucts = default(bool); + viewModel.DoorDriveTechnology = ConsumerTechnology.Pneumatically; } private void SetValues(IAuxiliariesViewModel auxiliaries) @@ -99,6 +102,7 @@ namespace VECTO3GUI.Model.TempDataObject HeatPump = auxiliaries.HeatPump; AdjustableAuxiliaryHeater = auxiliaries.AdjustableAuxiliaryHeater; SeparateAirDistributionDucts = auxiliaries.SeparateAirDistributionDucts; + DoorDriveTechnology = auxiliaries.DoorDriveTechnology; } } diff --git a/VECTO3GUI/Resources/AirdragLoadTestFile.xml b/VECTO3GUI/Resources/AirdragLoadTestFile.xml new file mode 100644 index 0000000000000000000000000000000000000000..3baab2fa609ec00fcb3b5095be0d7a63a5211f9d --- /dev/null +++ b/VECTO3GUI/Resources/AirdragLoadTestFile.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<tns:VectoInputDeclaration xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0" xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationComponent:v1.0" xmlns:di="http://www.w3.org/2000/09/xmldsig#" schemaVersion="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationComponent:v1.0 https://webgate.ec.europa.eu/CITnet/svn/VECTO/trunk/Share/XML/XSD/VectoComponent.xsd"> + <tns:AirDrag> + <Data id="TestAirDrag1234" xsi:type="AirDragDataDeclarationType"> + <Manufacturer>Test AirDrag Manufacturer</Manufacturer> + <Model>Test AirDrag Model</Model> + <CertificationNumber>e12*0815/8051*2020/05E0000*66</CertificationNumber> + <Date>2020-04-28T09:16:15.1270795Z</Date> + <AppVersion>Vecto AirDrag Test Load</AppVersion> + <CdxA_0>6.12</CdxA_0> + <TransferredCdxA>7.12</TransferredCdxA> + <DeclaredCdxA>8.12</DeclaredCdxA> + </Data> + <Signature> + <di:Reference URI="#TestAirDrag1234"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>Yd3UDJ/zKPhsmPadJeC4Ez/q7o3G82Zbq3mX3tSqLDw=</di:DigestValue> + </di:Reference> + </Signature> + </tns:AirDrag> +</tns:VectoInputDeclaration> \ No newline at end of file diff --git a/VECTO3GUI/Resources/GlobalStyles.xaml b/VECTO3GUI/Resources/GlobalStyles.xaml index 8a68ce29cae19a0a4780cae734818aacc8dd81c8..169b5b069ad9997acf92bdd79b254ffa002a8a70 100644 --- a/VECTO3GUI/Resources/GlobalStyles.xaml +++ b/VECTO3GUI/Resources/GlobalStyles.xaml @@ -56,7 +56,13 @@ <Setter Property="VerticalAlignment" Value="Center"/> </Style> - - - + <Style x:Key="textBoxInError" TargetType="{x:Type TextBox}" BasedOn="{StaticResource MetroTextBox}"> + <Style.Triggers> + <Trigger Property="Validation.HasError" Value="true"> + <Setter Property="ToolTip" + Value="{Binding RelativeSource={x:Static RelativeSource.Self}, + Path=(Validation.Errors)[0].ErrorContent}"/> + </Trigger> + </Style.Triggers> + </Style> </ResourceDictionary> \ No newline at end of file diff --git a/VECTO3GUI/Resources/ViewModelMappings.xaml b/VECTO3GUI/Resources/ViewModelMappings.xaml index ef7014a6439c3c949a02f76a8dd97098ae2acb76..a3321d13f7f2a1b1ee6ee1044fa9968d1af80cf8 100644 --- a/VECTO3GUI/Resources/ViewModelMappings.xaml +++ b/VECTO3GUI/Resources/ViewModelMappings.xaml @@ -23,7 +23,9 @@ <views:SettingsView/> </DataTemplate> - + <DataTemplate DataType="{x:Type impl:AbstractBusJobViewModel}"> + <views:BusJobView/> + </DataTemplate> <DataTemplate DataType="{x:Type impl:EngineOnlyJobViewModel}"> <views:JobEditView/> diff --git a/VECTO3GUI/Util/XML/XMLCompletedBus.cs b/VECTO3GUI/Util/XML/XMLCompletedBus.cs index 923fcc830d5b61a1ba5a131402a81b19e8b7ba69..078b13ad18f4476b7fb768b5fc0e0f9d29a0d2ca 100644 --- a/VECTO3GUI/Util/XML/XMLCompletedBus.cs +++ b/VECTO3GUI/Util/XML/XMLCompletedBus.cs @@ -130,7 +130,7 @@ namespace VECTO3GUI.Util.XML new XAttribute("xmlns", _v20), new XElement(_v20 + XMLNames.ComponentDataWrapper, - new XAttribute(XMLNames.Component_ID_Attr, airdrag.DigestValue.Reference), + new XAttribute(XMLNames.Component_ID_Attr, airdrag.DigestValue.Reference.Replace("#","")), new XAttribute(_xsi + "type", XMLDeclarationAirdragDataProviderV10.XSD_TYPE), // "AirDragDataDeclarationType" new XElement(_v20 + XMLNames.Component_Manufacturer, airdrag.Manufacturer), @@ -172,14 +172,16 @@ namespace VECTO3GUI.Util.XML new XElement(_v26 + XMLNames.Bus_Positionlights, auxBus?.PositionlightsLED), new XElement(_v26 + XMLNames.Bus_Brakelights, auxBus?.BrakelightsLED), new XElement(_v26 + XMLNames.Bus_Interiorlights, auxBus?.InteriorLightsLED))), + //----> ToDo remove if xsd gets changed <--- new XElement(_v26 + XMLNames.BusAux_PneumaticSystem, - new XElement(_v26 + XMLNames.BusAux_PneumaticSystem_DoorDriveTechnology)), + new XElement(_v26 + XMLNames.BusAux_PneumaticSystem_DoorDriveTechnology, auxBus?.DoorDriveTechnology.GetLabel().ToLower())), + //------------------------------------------ new XElement(_v26 + "HVAC", new XElement(_v26 + XMLNames.Bus_SystemConfiguration, auxBus?.SystemConfiguration.GetXmlFormat()), new XElement(_v26 + XMLNames.Bus_CompressorType, new XElement(_v26 + XMLNames.Bus_DriverAC, auxBus?.CompressorTypeDriver.GetLabel()), new XElement(_v26 + XMLNames.Bus_PassengerAC, auxBus?.CompressorTypePassenger.GetLabel())), - new XElement(_v26 + XMLNames.Bus_AuxiliaryHeaterPower, auxBus?.AuxHeaterPower.ToXMLFormat()), + new XElement(_v26 + XMLNames.Bus_AuxiliaryHeaterPower, Convert.ToInt32(auxBus?.AuxHeaterPower.Value())), new XElement(_v26 + XMLNames.Bus_DoubleGlasing, auxBus?.DoubleGlasing), new XElement(_v26 + XMLNames.Bus_HeatPump, auxBus?.HeatPump), new XElement(_v26 + XMLNames.Bus_AdjustableAuxiliaryHeater, auxBus?.AdjustableAuxiliaryHeater), diff --git a/VECTO3GUI/VECTO3GUI.csproj b/VECTO3GUI/VECTO3GUI.csproj index cc6925660946f92a0fa9b379eaa09443f001b617..0d9cbb0c7978339b89c6dfb9011e420b19c6b6af 100644 --- a/VECTO3GUI/VECTO3GUI.csproj +++ b/VECTO3GUI/VECTO3GUI.csproj @@ -123,6 +123,9 @@ <Reference Include="Microsoft.WindowsAPICodePack.Shell, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\packages\WindowsAPICodePack-Shell.1.1.1\lib\Microsoft.WindowsAPICodePack.Shell.dll</HintPath> </Reference> + <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> + </Reference> <Reference Include="Ninject, Version=3.3.4.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL"> <HintPath>..\packages\Ninject.3.3.4\lib\net45\Ninject.dll</HintPath> <Private>True</Private> @@ -161,11 +164,20 @@ <Compile Include="Helper\Converter\BoolVisibilityConverter.cs" /> <Compile Include="Helper\Converter\ComponentTitleConverter.cs" /> <Compile Include="Helper\Converter\EnumConverter.cs" /> + <Compile Include="Helper\EventCommandExecuter.cs" /> <Compile Include="Helper\Extension.cs" /> <Compile Include="Helper\FileDialogHelper.cs" /> + <Compile Include="Helper\MetroDialogHelper.cs" /> + <Compile Include="Helper\ObservableCollectionEx.cs" /> <Compile Include="Helper\OutputWindowHelper.cs" /> <Compile Include="Helper\Converter\SaveButtonLabelConverter.cs" /> + <Compile Include="Helper\SerializeHelper.cs" /> + <Compile Include="Helper\TextBoxInputRegExBehaviour.cs" /> + <Compile Include="Helper\ViewModelBase.cs" /> + <Compile Include="Helper\XmlComponentReaderHelper.cs" /> + <Compile Include="Helper\XmlHelper.cs" /> <Compile Include="Model\InterfacesImpl.cs" /> + <Compile Include="Model\JobListModel.cs" /> <Compile Include="Model\SettingsModel.cs" /> <Compile Include="Model\TempDataObject\AirdragComponentData.cs" /> <Compile Include="Model\TempDataObject\AuxiliariesBusComponentData.cs" /> @@ -193,6 +205,7 @@ <Compile Include="ViewModel\Adapter\Declaration\TyreDeclarationAdapter.cs" /> <Compile Include="ViewModel\Adapter\Declaration\VehicleDeclarationAdapter.cs" /> <Compile Include="ViewModel\Adapter\IAdapterFactory.cs" /> + <Compile Include="ViewModel\Impl\AbstractBusJobViewModel.cs" /> <Compile Include="ViewModel\Impl\AbstractComponentViewModel.cs" /> <Compile Include="ViewModel\Impl\AbstractJobViewModel.cs" /> <Compile Include="ViewModel\Impl\AbstractViewModel.cs" /> @@ -202,7 +215,7 @@ <Compile Include="ViewModel\Impl\AxlegearViewModel.cs" /> <Compile Include="ViewModel\Impl\AxlesViewModel.cs" /> <Compile Include="ViewModel\Impl\AxleViewModel.cs" /> - <Compile Include="ViewModel\Impl\BusJobViewModel.cs" /> + <Compile Include="ViewModel\Impl\CompletedBusJobViewModel.cs" /> <Compile Include="ViewModel\Impl\CompleteVehicleBusJobViewModel.cs" /> <Compile Include="ViewModel\Impl\CompleteVehicleBusViewModel.cs" /> <Compile Include="ViewModel\Impl\CyclesViewModel.cs" /> @@ -221,6 +234,7 @@ <Compile Include="ViewModel\Impl\PrimaryVehicleBusViewModel.cs" /> <Compile Include="ViewModel\Impl\RetarderViewModel.cs" /> <Compile Include="ViewModel\Impl\SettingsViewModel.cs" /> + <Compile Include="ViewModel\Impl\SingleBusJobViewModel.cs" /> <Compile Include="ViewModel\Impl\TorqueConverterViewModel.cs" /> <Compile Include="ViewModel\Impl\TyreViewModel.cs" /> <Compile Include="ViewModel\Impl\ValidatingViewModel.cs" /> @@ -238,6 +252,7 @@ <Compile Include="ViewModel\Interfaces\IAxlegearViewModel.cs" /> <Compile Include="ViewModel\Interfaces\IAxlesViewModel.cs" /> <Compile Include="ViewModel\Interfaces\IAxleViewModel.cs" /> + <Compile Include="ViewModel\Interfaces\IBusJobViewModel.cs" /> <Compile Include="ViewModel\Interfaces\ICommonComponentParameters.cs" /> <Compile Include="ViewModel\Interfaces\ICompleteVehicleBus.cs" /> <Compile Include="ViewModel\Interfaces\ICompleteVehicleBusViewModel.cs" /> @@ -613,7 +628,9 @@ <Name>VectoCore</Name> </ProjectReference> </ItemGroup> - <ItemGroup /> + <ItemGroup> + <Resource Include="Resources\AirdragLoadTestFile.xml" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. diff --git a/VECTO3GUI/ViewModel/Impl/AbstractBusJobViewModel.cs b/VECTO3GUI/ViewModel/Impl/AbstractBusJobViewModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..37c5556ff67357e1263700f690d733ee443e4d07 --- /dev/null +++ b/VECTO3GUI/ViewModel/Impl/AbstractBusJobViewModel.cs @@ -0,0 +1,291 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Input; +using System.Xml; +using Castle.Core.Internal; +using Ninject; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCore.InputData.FileIO.XML; +using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider; +using VECTO3GUI.Helper; +using VECTO3GUI.Model; +using VECTO3GUI.Util; +using VECTO3GUI.ViewModel.Interfaces; + +namespace VECTO3GUI.ViewModel.Impl +{ + + public enum JobFileType + { + CompletedBusFile, + PrimaryBusFile, + PIFBusFile + } + + public static class JobFileTypeHelper + { + public static string GetLable(this JobFileType fileType) + { + switch (fileType) + { + case JobFileType.CompletedBusFile: + return "Completed Bus File"; + case JobFileType.PrimaryBusFile: + return "Primary Bus File"; + case JobFileType.PIFBusFile: + return "PIF Bus File"; + default: + return string.Empty; + } + + } + } + + + + public abstract class AbstractBusJobViewModel : ViewModelBase, IBusJobViewModel + { + #region Members + + private JobFileType _firstFileType; + private JobFileType _secondFileType; + + private string _firstLabelText; + private string _secondLabelText; + private string _firstFilePath; + private string _secondFilePath; + + private ICommand _selectFirstFileCommand; + private ICommand _selectSecondFileCommand; + private ICommand _cancelCommand; + private ICommand _saveCommand; + + protected SettingsModel Settings { get; private set; } + + protected JobType JobType; + private readonly bool _editJob; + + #endregion + + #region Properties + + public JobEntry SavedJobEntry { get; private set; } + + public string FirstFilePath + { + get { return _firstFilePath; } + set { SetProperty(ref _firstFilePath, value); } + } + + public string SecondFilePath + { + get { return _secondFilePath; } + set { SetProperty(ref _secondFilePath, value); } + } + + public string FirstLabelText + { + get { return _firstLabelText; } + set { SetProperty(ref _firstLabelText, value); } + } + + public string SecondLabelText + { + get { return _secondLabelText; } + set { SetProperty(ref _secondLabelText, value); } + } + + public JobFileType FirstFileType + { + get { return _firstFileType; } + set { SetProperty(ref _firstFileType, value); } + } + public JobFileType SecondFileType + { + get { return _secondFileType; } + set { SetProperty(ref _secondFileType, value); } + } + + #endregion + + protected AbstractBusJobViewModel(IKernel kernel, JobType jobType) + { + Init(kernel, jobType); + _editJob = false; + } + + protected AbstractBusJobViewModel(IKernel kernel, JobEntry jobEntry) + { + Init(kernel, jobEntry.JobType); + SetJobEntryData(jobEntry); + SavedJobEntry = jobEntry; + _editJob = true; + } + + private void Init(IKernel kernel, JobType jobType) + { + SecondLabelText = $"Select {JobFileType.CompletedBusFile.GetLable()}"; + Settings = new SettingsModel(); + SetFileTypes(jobType); + Kernel = kernel; + } + + private void SetFileTypes(JobType jobType) + { + JobType = jobType; + + _firstFileType = jobType == JobType.SingleBusJob + ? JobFileType.PrimaryBusFile + : JobFileType.PIFBusFile; + + _secondFileType = JobFileType.CompletedBusFile; + } + + private void SetJobEntryData(JobEntry jobEntry) + { + FirstFilePath = jobEntry.FirstFilePath; + SecondFilePath = jobEntry.SecondFilePath; + } + + protected abstract void SetFirstFileLabel(); + + #region Commands + + public ICommand SelectFirstFileCommand + { + get + { + return _selectFirstFileCommand ?? + (_selectFirstFileCommand = new RelayCommand<JobFileType>(DoSelectFirstFileCommand)); + } + } + private void DoSelectFirstFileCommand(JobFileType jobFileType) + { + FirstFilePath = OpenFileSelector(jobFileType, nameof(FirstFilePath)); + } + + public ICommand SelectSecondFileCommand + { + get + { + return _selectSecondFileCommand ?? + (_selectSecondFileCommand = new RelayCommand<JobFileType>(DoSelectSecondFileCommand)); + } + } + private void DoSelectSecondFileCommand(JobFileType jobFileType) + { + SecondFilePath = OpenFileSelector(jobFileType, nameof(SecondFilePath)); + } + + public ICommand CancelCommand + { + get { return _cancelCommand ?? (_cancelCommand = new RelayCommand<Window>(DoCancelCommand)); } + } + private void DoCancelCommand(Window window) + { + window.Close(); + } + + public ICommand SaveCommand + { + get { return _saveCommand ?? (_saveCommand = new RelayCommand<Window>(DoSaveCommand, CanSaveCommand)); } + } + private bool CanSaveCommand(Window window) + { + return !HasErrors && !FirstFilePath.IsNullOrEmpty() && !SecondFilePath.IsNullOrEmpty(); + } + private void DoSaveCommand(Window window) + { + window.DialogResult = true; + if (!_editJob) + SaveJob(window); + else + UpdateJobData(); + } + + #endregion + + private void SaveJob(Window window) + { + var jobFilePath = FileDialogHelper.SaveJobFileToDialog(Settings.XmlFilePathFolder); + if (jobFilePath != null) { + + var job = new JobEntry { + JobEntryFilePath = jobFilePath, + FirstFilePath = FirstFilePath, + SecondFilePath = SecondFilePath, + JobType = JobType + }; + + SerializeHelper.SerializeToFile(jobFilePath, job); + SavedJobEntry = job; + DoCancelCommand(window); + } + } + + private void UpdateJobData() + { + SavedJobEntry.FirstFilePath = FirstFilePath; + SavedJobEntry.SecondFilePath = SecondFilePath; + } + + + private string OpenFileSelector(JobFileType jobFileType, string textPropertyName) + { + var dialogResult = FileDialogHelper.ShowSelectFilesDialog(false, FileDialogHelper.XMLFilter, Settings.XmlFilePathFolder); + if (dialogResult == null) + return null; + + var filePath = dialogResult.FirstOrDefault(); + var validationResult = IsValideXml(jobFileType, filePath); + + if (!validationResult) + AddPropertyError(textPropertyName, $"Selected XML-File is not a valid {jobFileType.GetLable()}!"); + else + RemovePropertyError(textPropertyName); + + return !validationResult ? null : filePath; + } + + private bool IsValideXml(JobFileType jobFileType, string filePath) + { + if (filePath.IsNullOrEmpty()) + return false; + + var xmlInputReader = Kernel.Get<IXMLInputDataReader>(); + + using (var reader = XmlReader.Create(filePath)) + { + + var readerResult = xmlInputReader.Create(reader); + if (readerResult is IDeclarationInputDataProvider) + { + + var inputData = readerResult as IDeclarationInputDataProvider; + if (jobFileType == JobFileType.CompletedBusFile && + inputData.JobInputData.Vehicle is XMLDeclarationCompletedBusDataProviderV26) + { + return true; + } + if (jobFileType == JobFileType.PrimaryBusFile && + inputData.JobInputData.Vehicle is XMLDeclarationPrimaryBusVehicleDataProviderV26) + { + return true; + } + } + else if (readerResult is IPrimaryVehicleInformationInputDataProvider) + { + var inputData = readerResult as IPrimaryVehicleInformationInputDataProvider; + if (jobFileType == JobFileType.PIFBusFile && + inputData.Vehicle is XMLDeclarationPrimaryVehicleBusDataProviderV01) + return true; + } + return false; + } + } + } +} diff --git a/VECTO3GUI/ViewModel/Impl/AbstractJobViewModel.cs b/VECTO3GUI/ViewModel/Impl/AbstractJobViewModel.cs index db2d12879ac09cc44c5ee99fc6f3083723aa8103..76044356820eff24bb397fba78bcfd9eeb07d99c 100644 --- a/VECTO3GUI/ViewModel/Impl/AbstractJobViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/AbstractJobViewModel.cs @@ -1,23 +1,34 @@ using System; +using System.ComponentModel; using System.Linq; using System.Windows; -using System.Windows.Controls; using System.Windows.Input; +using MahApps.Metro.Controls.Dialogs; using Ninject; +using VECTO3GUI.Helper; +using VECTO3GUI.Model; using VECTO3GUI.Util; using VECTO3GUI.ViewModel.Interfaces; +using Component = VECTO3GUI.Util.Component; namespace VECTO3GUI.ViewModel.Impl { public abstract class AbstractJobViewModel : AbstractViewModel { protected bool IsDeclarationMode; + protected bool WindowAlreadyClosed; + protected readonly SettingsModel SettingsModel; + private IComponentViewModel _currentComponent; private ICommand _saveJobCommand; private ICommand _closeJobCommand; private ICommand _saveToJobCommand; + protected string XmlFilePath { get; private set; } + + protected bool IsNewJob { get; set; } + public override bool DeclarationMode { get { return IsDeclarationMode; } @@ -31,39 +42,69 @@ namespace VECTO3GUI.ViewModel.Impl } } + public AbstractJobViewModel() + { + SettingsModel = new SettingsModel(); + } + public ICommand SaveJob { - get { return _saveJobCommand ?? (_saveJobCommand = new RelayCommand(DoSaveJob)); } + get { return _saveJobCommand ?? (_saveJobCommand = new RelayCommand<Window>(DoSaveJob, CanSaveJob)); } + } + protected virtual bool CanSaveJob(Window window) + { + return true; } + protected abstract void DoSaveJob(Window window); - protected abstract void DoSaveJob(); public ICommand CloseJob { - get { return _closeJobCommand ?? (_closeJobCommand = new RelayCommand<Window>(DoCloseJob));} + get { return _closeJobCommand ?? (_closeJobCommand = new RelayCommand<Window>(DoCloseJob, CanCloseJob));} + } + protected virtual bool CanCloseJob(Window obj) + { + return true; } - protected abstract void DoCloseJob(Window window); public ICommand SaveToJob { - get { return _saveToJobCommand ?? (_saveToJobCommand = new RelayCommand(DoSaveToJob)); } + get { return _saveToJobCommand ?? (_saveToJobCommand = new RelayCommand<Window>(DoSaveToJob, CanSaveToJob)); } + } + protected virtual bool CanSaveToJob(Window window) + { + return true; } + protected abstract void DoSaveToJob(Window window); - protected abstract void DoSaveToJob(); public ICommand EditComponent { get { return new RelayCommand<Component>(DoEditComponent); } } - protected virtual void DoEditComponent(Component component) { var nextView = GetComponentViewModel(component); CurrentComponent = nextView ?? Kernel.Get<INoneViewModel>(); } + public ICommand CloseWindowCommand + { + get { return new RelayCommand<CancelEventArgs>(DoCloseWindow);} + } + + private void DoCloseWindow(CancelEventArgs cancelEvent) + { + if (WindowAlreadyClosed) + return; + + if(!CloseWindowDialog()) + cancelEvent.Cancel = true; + } + + protected void CreateComponentModel(Component component) { var viewModelType = ViewModelFactory.ComponentViewModelMapping[component]; @@ -77,5 +118,30 @@ namespace VECTO3GUI.ViewModel.Impl RegisterSubmodel(component, viewModel); } } + + protected void SetXmlFilePath(string baseUri) + { + if (baseUri == null) + return; + + var uri = new Uri(baseUri); + XmlFilePath = uri.AbsolutePath; + } + + protected bool CloseWindowDialog() + { + var dialogSettings = new MetroDialogSettings() + { + AffirmativeButtonText = "Yes", + NegativeButtonText = "No", + AnimateShow = true, + AnimateHide = true + }; + + var res = MetroDialogHelper.GetModalDialogBox(this, + "", "Do you really want to close ?", dialogSettings); + + return res == MessageDialogResult.Affirmative; + } } } diff --git a/VECTO3GUI/ViewModel/Impl/AirdragViewModel.cs b/VECTO3GUI/ViewModel/Impl/AirdragViewModel.cs index 20504eda8d0ebf7d265941d45132d91e65425101..70ae9f5f19bdfe9d8f88fc9166903539ffbdbb78 100644 --- a/VECTO3GUI/ViewModel/Impl/AirdragViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/AirdragViewModel.cs @@ -1,15 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Windows.Forms; using System.Windows.Input; -using System.Xml; +using Castle.Core.Internal; using Ninject; +using TUGraz.VectoCommon.Hashing; using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Resources; using TUGraz.VectoCommon.Utils; -using TUGraz.VectoCore.InputData.FileIO.XML; -using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader; -using TUGraz.VectoCore.Utils; using VECTO3GUI.Helper; using VECTO3GUI.Model.TempDataObject; using VECTO3GUI.Util; @@ -65,7 +63,10 @@ namespace VECTO3GUI.ViewModel.Impl private IAirdragDeclarationInputData _airdragData; private AirdragComponentData _componentData; private bool _isEditable; - + private bool _useMeasurementData; + private bool _noAirdragData; + + private ICommand _airdragConfig; private ICommand _loadFileCommand; @@ -126,7 +127,6 @@ namespace VECTO3GUI.ViewModel.Impl { if (!SetProperty(ref _date, value)) return; - IsDataChanged(_date, _componentData); } } @@ -138,9 +138,7 @@ namespace VECTO3GUI.ViewModel.Impl { if (!SetProperty(ref _declaredCdxA, value)) return; - IsDataChanged(_declaredCdxA, _componentData); - SetAirdragArea(_airdragData); } } @@ -165,13 +163,27 @@ namespace VECTO3GUI.ViewModel.Impl set { SetProperty(ref _isEditable, value); } } + public bool UseMeasurementData + { + get { return _useMeasurementData; } + set { SetProperty(ref _useMeasurementData, value); } + } + + public bool NoAirdragData + { + get { return _noAirdragData; } + set { SetProperty(ref _noAirdragData, value); } + } + protected override void InputDataChanged() { var inputData = JobViewModel.InputDataProvider as IDeclarationInputDataProvider; _airdragData = inputData?.JobInputData.Vehicle.Components.AirdragInputData; SetAirdragValues(_airdragData); - IsEditable = true; + UseMeasurementData = _airdragData != null; + NoAirdragData = !UseMeasurementData; + IsEditable = false; } private void SetAirdragValues(IAirdragDeclarationInputData airdrag) @@ -188,7 +200,9 @@ namespace VECTO3GUI.ViewModel.Impl CertificationNumber = airdrag.CertificationNumber; Date = airdrag.Date; AppVersion = airdrag.AppVersion; - SetAirdragArea(airdrag); + DeclaredCdxA = airdrag.AirDragArea; + CdxA_0 = DeclaredCdxA; + TransferredCdxA = DeclaredCdxA; DigestValue = airdrag.DigestValue; _componentData = new AirdragComponentData(this); @@ -207,7 +221,7 @@ namespace VECTO3GUI.ViewModel.Impl private void DoAirdragConfig(AirdragConfig config) { - IsEditable = config == AirdragConfig.UseMeasurementData; + } @@ -221,25 +235,17 @@ namespace VECTO3GUI.ViewModel.Impl private bool CanLoadFile() { - return IsEditable; + return UseMeasurementData; } private void DoLoadFile() { var filePath = FileDialogHelper.ShowSelectFilesDialog(false)?.FirstOrDefault(); - ReadSelectedXml(null); + ReadSelectedXml(filePath); } #endregion - - private void SetAirdragArea(IAirdragDeclarationInputData airdrag) - { - DeclaredCdxA = airdrag.AirDragArea; - CdxA_0 = DeclaredCdxA; - TransferredCdxA = DeclaredCdxA; - } - public override void ResetComponentData() { _componentData.ResetToComponentValues(this); @@ -254,8 +260,34 @@ namespace VECTO3GUI.ViewModel.Impl private void ReadSelectedXml(string filePath) { - if (filePath == null) + if (filePath.IsNullOrEmpty()) return; + + var xmlDocument = XmlHelper.ReadXmlDocument(filePath); + var nodes = XmlHelper.GetComponentNodes(xmlDocument, + XMLNames.VectoInputDeclaration, VectoComponents.Airdrag.XMLElementName()); + + if(nodes.IsNullOrEmpty()) + return; + + var compReader = new XmlComponentReaderHelper(nodes[0].ParentNode); + SetLoadedAirdragData(compReader.GetAirdragComponentData()); + } + + private void SetLoadedAirdragData(AirdragComponentData airdrag) + { + if (airdrag == null) + return; + + Model = airdrag.Model; + Manufacturer = airdrag.Manufacturer; + CertificationNumber = airdrag.CertificationNumber; + Date = airdrag.Date; + AppVersion = airdrag.AppVersion; + DeclaredCdxA = airdrag.DeclaredCdxA; + CdxA_0 = airdrag.CdxA_0; + TransferredCdxA = airdrag.TransferredCdxA; + DigestValue = airdrag.DigestValue; } } } diff --git a/VECTO3GUI/ViewModel/Impl/AuxiliariesViewModel.cs b/VECTO3GUI/ViewModel/Impl/AuxiliariesViewModel.cs index e6b09c1825d18a81bef4d0eb291e0844d11a06b1..61fa55736a855f19eb2346021d7ecf9502a07355 100644 --- a/VECTO3GUI/ViewModel/Impl/AuxiliariesViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/AuxiliariesViewModel.cs @@ -273,7 +273,9 @@ namespace VECTO3GUI.ViewModel.Impl } } - + public ConsumerTechnology DoorDriveTechnology { get; set; } + + public AllowedEntry<BusHVACSystemConfiguration>[] AllowedSystemConfigurations { get; private set; } public AllowedEntry<ACCompressorType>[] AllowedDriverACCompressorTypes { get; private set; } public AllowedEntry<ACCompressorType>[] AllowedPassengerACCompressorTypes { get; private set; } @@ -319,8 +321,8 @@ namespace VECTO3GUI.ViewModel.Impl AlternatorTechnologies.Add(busAux.ElectricSupply.Alternators[i].Technology); } - AlternatorTechnologies.Add("blu"); - AlternatorTechnologies.Add("bla"); + //AlternatorTechnologies.Add("blu"); + //AlternatorTechnologies.Add("bla"); } DayrunninglightsLED = busAux.ElectricConsumers.DayrunninglightsLED; @@ -336,6 +338,7 @@ namespace VECTO3GUI.ViewModel.Impl HeatPump = busAux.HVACAux.HeatPump; AdjustableAuxiliaryHeater = busAux.HVACAux.AdjustableAuxiliaryHeater; SeparateAirDistributionDucts = busAux.HVACAux.SeparateAirDistributionDucts; + DoorDriveTechnology = ConsumerTechnology.Pneumatically; _componentData = new AuxiliariesBusComponentData(this); ClearChangedProperties(); diff --git a/VECTO3GUI/ViewModel/Impl/BusJobViewModel.cs b/VECTO3GUI/ViewModel/Impl/BusJobViewModel.cs deleted file mode 100644 index ea0898ad578ad45264caf7f7f8910342f2051eb1..0000000000000000000000000000000000000000 --- a/VECTO3GUI/ViewModel/Impl/BusJobViewModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace VECTO3GUI.ViewModel.Impl -{ - public class BusJobViewModel : ObservableObject - { - } -} diff --git a/VECTO3GUI/ViewModel/Impl/CompleteVehicleBusJobViewModel.cs b/VECTO3GUI/ViewModel/Impl/CompleteVehicleBusJobViewModel.cs index 0e0246630aa09367626f172971fa32ae12b388c0..d414dcacfcf0548f5b2f56dd2e19855c1b766db4 100644 --- a/VECTO3GUI/ViewModel/Impl/CompleteVehicleBusJobViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/CompleteVehicleBusJobViewModel.cs @@ -5,21 +5,25 @@ using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; +using MahApps.Metro.Controls.Dialogs; using Ninject; using TUGraz.VectoCommon.InputData; -using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.OutputData.XML.DeclarationJobs; -using VECTO3GUI.Model.TempDataObject; +using VECTO3GUI.Helper; using VECTO3GUI.ViewModel.Interfaces; using VECTO3GUI.Util; using VECTO3GUI.Util.XML; + namespace VECTO3GUI.ViewModel.Impl { public class CompleteVehicleBusJobViewModel : AbstractJobViewModel, IJobEditViewModel { #region Members - + + private readonly XMLCompletedBus _xmlCompletedBus; + private readonly XMLCompletedBusWriter _xmlCompletedBusWriter; + private ICommand _saveComponentCommand; private ICommand _resetComponentCommand; @@ -35,45 +39,69 @@ namespace VECTO3GUI.ViewModel.Impl { Kernel = kernel; InputDataProvider = inputData; + IsNewJob = inputData == null; JobViewModel = this; CreateComponentModel(Component.CompleteBusVehicle); CreateComponentModel(Component.Airdrag); CreateComponentModel(Component.Auxiliaries); CurrentComponent = GetComponentViewModel(Component.CompleteBusVehicle); - } - - #region Commands + SetXmlFilePath(inputData?.JobInputData.Vehicle.XMLSource.BaseURI); - + _xmlCompletedBus = new XMLCompletedBus(); + _xmlCompletedBusWriter = new XMLCompletedBusWriter(); + } + #region Commands - - protected override void DoSaveJob() + protected override bool CanSaveJob(Window window) { - CompleteVehicleBusData = new Dictionary<Component, object> { - { Component.CompleteBusVehicle, _subModels[Component.CompleteBusVehicle].SaveComponentData()}, - { Component.Airdrag, _subModels[Component.Airdrag].SaveComponentData()}, - { Component.Auxiliaries, _subModels[Component.Auxiliaries].SaveComponentData()} + return !IsNewJob; + } + protected override void DoSaveJob(Window window) + { + var dialogSettings = new MetroDialogSettings() + { + AffirmativeButtonText = "Yes", + NegativeButtonText = "Cancel", + AnimateShow = true, + AnimateHide = true }; - - - //var completedXml = new XMLCompletedBus(); - //var xmlDoc = completedXml.GenerateCompletedBusDocument(CompleteVehicleBusData); - - //var writer = new XMLCompletedBusWriter(); - //writer.WriteCompletedBusXml(filePath, xmlDoc); + + var dialogResult = MetroDialogHelper.GetModalDialogBox(this, "Save", + "The existing file will be overwritten, do you want to continue?", + MessageDialogStyle.AffirmativeAndNegative, dialogSettings); + + if (dialogResult == MessageDialogResult.Affirmative) { + SetCurrentDataToSave(); + var xDoc = _xmlCompletedBus.GenerateCompletedBusDocument(CompleteVehicleBusData); + + if (XmlHelper.ValidateXDocument(xDoc)) { + _xmlCompletedBusWriter.WriteCompletedBusXml(XmlFilePath, xDoc); + CloseWindow(window); + } + } } protected override void DoCloseJob(Window window) { - window?.Close(); + if (CloseWindowDialog()) { + CloseWindow(window); + } } - protected override void DoSaveToJob() + protected override void DoSaveToJob(Window window) { - + var filePath = FileDialogHelper.SaveXmlFileToDialog(SettingsModel.XmlFilePathFolder); + + SetCurrentDataToSave(); + var xDocument = _xmlCompletedBus.GenerateCompletedBusDocument(CompleteVehicleBusData); + + if (XmlHelper.ValidateXDocument(xDocument)) { + _xmlCompletedBusWriter.WriteCompletedBusXml(filePath, xDocument); + CloseWindow(window); + } } public ICommand SaveComponent @@ -108,14 +136,10 @@ namespace VECTO3GUI.ViewModel.Impl get { return _resetComponentCommand ?? (_resetComponentCommand = new RelayCommand<Component>(DoResetComponent, CanResetComponent)); } } - - private bool CanResetComponent(Component component) { return ComponentsChanged(component); - } - - private void DoResetComponent(Component component) + }private void DoResetComponent(Component component) { switch (component) { @@ -133,7 +157,15 @@ namespace VECTO3GUI.ViewModel.Impl #endregion - + private void SetCurrentDataToSave() + { + CompleteVehicleBusData = new Dictionary<Component, object> { + { Component.CompleteBusVehicle, _subModels[Component.CompleteBusVehicle].SaveComponentData()}, + { Component.Airdrag, _subModels[Component.Airdrag].SaveComponentData()}, + { Component.Auxiliaries, _subModels[Component.Auxiliaries].SaveComponentData()} + }; + } + private bool ComponentsChanged(Component component) { switch (component) { @@ -148,6 +180,12 @@ namespace VECTO3GUI.ViewModel.Impl } } + private void CloseWindow(Window window) + { + WindowAlreadyClosed = true; + window?.Close(); + } + public string JobFile { get; } public IInputDataProvider InputDataProvider { get; set; } diff --git a/VECTO3GUI/ViewModel/Impl/CompletedBusJobViewModel.cs b/VECTO3GUI/ViewModel/Impl/CompletedBusJobViewModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..eaae17058bbc967f919b2f2d57cf827a00659b9f --- /dev/null +++ b/VECTO3GUI/ViewModel/Impl/CompletedBusJobViewModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Ninject; + +namespace VECTO3GUI.ViewModel.Impl +{ + public class CompletedBusJobViewModel: AbstractBusJobViewModel + { + public CompletedBusJobViewModel(IKernel kernel, JobType jobType):base(kernel, jobType) + { + SetFirstFileLabel(); + } + + public CompletedBusJobViewModel(IKernel kernel, JobEntry jobEntry) : base(kernel, jobEntry) + { + SetFirstFileLabel(); + } + + protected sealed override void SetFirstFileLabel() + { + FirstLabelText = $"Select {JobFileType.PIFBusFile.GetLable()}"; + } + } +} diff --git a/VECTO3GUI/ViewModel/Impl/DeclarationJobViewModel.cs b/VECTO3GUI/ViewModel/Impl/DeclarationJobViewModel.cs index d7243c341a4ae4fac8ebaf417733b094c38792fe..b55d31550846b85cf7fe3d2b8257959b246adfdc 100644 --- a/VECTO3GUI/ViewModel/Impl/DeclarationJobViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/DeclarationJobViewModel.cs @@ -59,7 +59,7 @@ namespace VECTO3GUI.ViewModel.Impl } - protected override void DoSaveJob() + protected override void DoSaveJob(Window window) { var writer = new XMLDeclarationWriter("TEST"); var tmp = writer.GenerateVectoJob(ModelData); @@ -70,7 +70,7 @@ namespace VECTO3GUI.ViewModel.Impl throw new NotImplementedException(); } - protected override void DoSaveToJob() + protected override void DoSaveToJob(Window window) { throw new NotImplementedException(); } diff --git a/VECTO3GUI/ViewModel/Impl/EngineOnlyJobViewModel.cs b/VECTO3GUI/ViewModel/Impl/EngineOnlyJobViewModel.cs index 9791a60004e7707815d9aef2579f837687dae1d8..1fd5a9f413815247fc1ee3ae38442d66697a2e7a 100644 --- a/VECTO3GUI/ViewModel/Impl/EngineOnlyJobViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/EngineOnlyJobViewModel.cs @@ -50,7 +50,7 @@ namespace VECTO3GUI.ViewModel.Impl #region Overrides of AbstractJobViewModel - protected override void DoSaveJob() + protected override void DoSaveJob(Window window) { throw new System.NotImplementedException(); } @@ -60,7 +60,7 @@ namespace VECTO3GUI.ViewModel.Impl throw new System.NotImplementedException(); } - protected override void DoSaveToJob() + protected override void DoSaveToJob(Window window) { throw new System.NotImplementedException(); } diff --git a/VECTO3GUI/ViewModel/Impl/JobEntry.cs b/VECTO3GUI/ViewModel/Impl/JobEntry.cs index f5b65b148b8e7a0b13a59a9d17ee33f7f0c7db0f..936da2c900827691ce3a1f0588f2788e40282a3f 100644 --- a/VECTO3GUI/ViewModel/Impl/JobEntry.cs +++ b/VECTO3GUI/ViewModel/Impl/JobEntry.cs @@ -1,11 +1,98 @@ -namespace VECTO3GUI.ViewModel.Impl { +using System; +using Newtonsoft.Json; + +namespace VECTO3GUI.ViewModel.Impl +{ + public enum JobType + { + SingleBusJob, + CompletedBusJob, + Unknown + } + + public static class JobTypeHelper + { + private const string SingleBusJobLabel = "Single Bus Job"; + private const string CompletedBusJobLabel = "Completed Bus Job"; + + + public static string GetLabel(this JobType jobType) + { + switch (jobType) + { + case JobType.SingleBusJob: + return SingleBusJobLabel; + case JobType.CompletedBusJob: + return CompletedBusJobLabel; + default: + return string.Empty; + } + } + + public static JobType Parse(this string jobTypeName) + { + if (SingleBusJobLabel == jobTypeName) + return JobType.SingleBusJob; + if (CompletedBusJobLabel == jobTypeName) + return JobType.CompletedBusJob; + return JobType.Unknown; + } + } + + [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] public class JobEntry : ObservableObject { + private JobType _jobType; + private string _jobTypeName; private bool _selected; - private string _filename; + private string _jobEntryFilePath; + private string _firstFilePath; + private string _secondFilePath; + [JsonIgnore] public int Sorting; - public bool Selected { get { return _selected; } set { SetProperty(ref _selected, value); } } - public string Filename { get { return _filename; } set { SetProperty(ref _filename, value); } } + + [JsonIgnore] + public JobType JobType + { + get { return _jobType;} + set + { + _jobType = value; + _jobTypeName = _jobType.GetLabel(); + } + } + + public string JobTypeName + { + get { return _jobTypeName; } + set + { + _jobTypeName = value; + _jobType = _jobTypeName.Parse(); + } + } + + public bool Selected + { + get { return _selected; } + set { SetProperty(ref _selected, value); } + } + + public string JobEntryFilePath + { + get { return _jobEntryFilePath; } + set { SetProperty(ref _jobEntryFilePath, value); } + } + public string FirstFilePath + { + get { return _firstFilePath; } + set { SetProperty(ref _firstFilePath, value); } + } + public string SecondFilePath + { + get { return _secondFilePath; } + set { SetProperty(ref _secondFilePath, value); } + } } } \ No newline at end of file diff --git a/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs b/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs index e91caa0dd93d16b17adb950961d8b49590597937..f0646e800ff3e937ba42adab628ded11c56fe0dd 100644 --- a/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs @@ -1,29 +1,20 @@ using System; using System.Collections; using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Diagnostics; using System.IO; using System.Linq; using System.Windows; -using System.Windows.Controls; -using System.Windows.Documents; using System.Windows.Input; +using System.Xml; +using Castle.Core.Internal; using Ninject; -using Ninject.Parameters; -using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.InputData; -using TUGraz.VectoCore.Configuration; -using TUGraz.VectoCore.InputData.FileIO.JSON; using TUGraz.VectoCore.InputData.FileIO.XML; -using TUGraz.VectoCore.InputData.FileIO.XML.Declaration; -using TUGraz.VectoCore.InputData.FileIO.XML.Engineering; -using TUGraz.VectoCore.Utils; using VECTO3GUI.Util; using VECTO3GUI.ViewModel.Interfaces; -using System.Xml; -using System.Xml.Linq; -using Microsoft.WindowsAPICodePack.Shell.PropertySystem; -using TUGraz.VectoCommon.Resources; -using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider; using VECTO3GUI.Helper; using VECTO3GUI.Model; using VECTO3GUI.Views; @@ -35,16 +26,13 @@ namespace VECTO3GUI.ViewModel.Impl { #region Members - protected readonly ObservableCollection<JobEntry> _jobs = new ObservableCollection<JobEntry>(); + protected ObservableCollectionEx<JobEntry> _jobs; protected readonly ObservableCollection<MessageEntry> _messages = new ObservableCollection<MessageEntry>(); private readonly SettingsModel _settings; + private string _firstContextMenu; private JobEntry _selectedJobEntry; - - #endregion - - - #region Commands + private JobListModel _jobListModel; private ICommand _newJobCommand; private ICommand _editJobCommand; @@ -53,9 +41,13 @@ namespace VECTO3GUI.ViewModel.Impl private ICommand _addJobCommand; private ICommand _openJobCommand; private ICommand _openSettingsCommand; - private ICommand _exitCommand; private ICommand _exitMainCommand; private ICommand _addBusJobCommand; + private ICommand _editCompletedFileCommand; + private ICommand _moveJobUpCommand; + private ICommand _moveJobDownCommand; + private ICommand _startSimulationCommand; + private ICommand _openInFolderCommand; #endregion @@ -64,12 +56,22 @@ namespace VECTO3GUI.ViewModel.Impl public JobEntry SelectedJobEntry { get { return _selectedJobEntry; } - set { SetProperty(ref _selectedJobEntry, value); } + set + { + SetProperty(ref _selectedJobEntry, value); + if (_selectedJobEntry != null) { + var firstJobTyp = _selectedJobEntry.JobType == JobType.SingleBusJob + ? JobFileType.PrimaryBusFile + : JobFileType.PIFBusFile; + FirstContextMenu = $"View {firstJobTyp.GetLable()}"; + } + } } - public ObservableCollection<JobEntry> Jobs + public ObservableCollectionEx<JobEntry> Jobs { get { return _jobs; } + set { SetProperty(ref _jobs, value); } } public ObservableCollection<MessageEntry> Messages @@ -77,9 +79,14 @@ namespace VECTO3GUI.ViewModel.Impl get { return _messages; } } + public string FirstContextMenu + { + get { return _firstContextMenu; } + set { SetProperty(ref _firstContextMenu, value); } + } #endregion - + public JoblistViewModel() { _settings = new SettingsModel(); @@ -88,41 +95,47 @@ namespace VECTO3GUI.ViewModel.Impl private void SetJobEntries() { - var xmlFiles = Directory.GetFiles(_settings.XmlFilePathFolder, "*.xml"); - for (int i = 0; i < xmlFiles.Length; i++) { - AddJobEntry(xmlFiles[i]); - } + _jobListModel = new JobListModel(); + _jobs = new ObservableCollectionEx<JobEntry>(_jobListModel.GetJobEntries()); + _jobs.CollectionChanged += JobsCollectionChanged; + _jobs.CollectionItemChanged += JobItemChanged; } - private void AddJobEntry(string jobFile) + private void JobItemChanged(object sender, PropertyChangedEventArgs e) { - _jobs.Add(new JobEntry() - { - Filename = jobFile, - Selected = false, - Sorting = _jobs.Count - }); + if (e.PropertyName == "Selected" && sender is JobEntry) + UpdateJobEntry((JobEntry)sender); } + private void JobsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + case NotifyCollectionChangedAction.Remove: + case NotifyCollectionChangedAction.Move: + case NotifyCollectionChangedAction.Reset: + _jobListModel.SaveJobList(_jobs); + break; + } + } - #region Implementation IJoblistViewModel + #region Commands public ICommand RemoveJob { get { - return _removeJobCommand ?? - (_removeJobCommand = new RelayCommand(DoRemoveJob, CanRemoveJob)); + return _removeJobCommand ?? (_removeJobCommand = new RelayCommand<JobEntry>(DoRemoveJob, CanRemoveJob)); } } - private void DoRemoveJob() + private void DoRemoveJob(JobEntry jobEntry) { - _jobs.Remove(SelectedJobEntry); - SelectedJobEntry = null; + _jobs.Remove(jobEntry); } - private bool CanRemoveJob() + private bool CanRemoveJob(JobEntry jobEntry) { - return SelectedJobEntry != null; + return jobEntry != null; } @@ -130,8 +143,7 @@ namespace VECTO3GUI.ViewModel.Impl { get { - return _removeAllJobCommand ?? - (_removeAllJobCommand = new RelayCommand(DoRemoveAllJobs)); + return _removeAllJobCommand ?? (_removeAllJobCommand = new RelayCommand(DoRemoveAllJobs)); } } private void DoRemoveAllJobs() @@ -139,38 +151,51 @@ namespace VECTO3GUI.ViewModel.Impl _jobs.Clear(); SelectedJobEntry = null; } - + public ICommand EditJob { get { - return _editJobCommand ?? - (_editJobCommand = new RelayCommand(DoEditJob, CanEditJob)); + return _editJobCommand ?? (_editJobCommand = new RelayCommand<JobEntry>(DoEditJob, CanEditJob)); } } - private void DoEditJob() + private bool CanEditJob(JobEntry jobEntry) { - var entry = SelectedJobEntry; - try - { - var jobEditView = ReadJob(entry.Filename); //Kernel.Get<IJobEditViewModel>(); - if (jobEditView == null) - return; + return jobEntry != null; + } + private void DoEditJob(JobEntry jobEntry) + { + var viewModel = GetBusJobViewModel(jobEntry.JobType, jobEntry); + var window = CreateBusJobOutputWindow(viewModel, jobEntry.JobType); + if (window.ShowDialog() != true) + ResetBusJobEntries(jobEntry); + else + UpdateJobEntry(((IBusJobViewModel)viewModel).SavedJobEntry); + } - var window = OutputWindowHelper.CreateOutputWindow(Kernel, jobEditView); - window.Show(); - } - catch (Exception e) + + public ICommand EditCompletedFile + { + get { - MessageBox.Show( - "Failed to read selected job: " + Environment.NewLine + Environment.NewLine + e.Message, "Failed reading Job", - MessageBoxButton.OK); + return _editCompletedFileCommand ?? + (_editCompletedFileCommand = + new RelayCommand<JobEntry>(DoEditCompletedFile, CanEditCompletdFile)); } } - private bool CanEditJob() + private bool CanEditCompletdFile(JobEntry jobEntry) + { + return jobEntry != null; + } + private void DoEditCompletedFile(JobEntry jobEntry) { - return SelectedJobEntry != null; + var viewModel = ReadCompletedXmlFile(jobEntry); + if (viewModel == null) + return; + + var window = OutputWindowHelper.CreateOutputWindow(Kernel, viewModel); + window.Show(); } @@ -178,8 +203,7 @@ namespace VECTO3GUI.ViewModel.Impl { get { - return _newJobCommand ?? - (_newJobCommand = new RelayCommand(DoNewJobCommand)); + return _newJobCommand ?? (_newJobCommand = new RelayCommand(DoNewJobCommand)); } } private void DoNewJobCommand() @@ -194,16 +218,25 @@ namespace VECTO3GUI.ViewModel.Impl { get { - return _openJobCommand ?? - (_openJobCommand = new RelayCommand(DoOpenJobCommand)); + return _openJobCommand ?? (_openJobCommand = new RelayCommand<JobFileType>(DoOpenJobCommand)); } } - private void DoOpenJobCommand() + private void DoOpenJobCommand(JobFileType jobFileType) { if (SelectedJobEntry == null) return; - var xmlViewModel = new XMLViewModel(SelectedJobEntry.Filename); + XMLViewModel xmlViewModel = null; + + switch (jobFileType) { + case JobFileType.PIFBusFile: + case JobFileType.PrimaryBusFile: + xmlViewModel = new XMLViewModel(SelectedJobEntry.FirstFilePath); + break; + case JobFileType.CompletedBusFile: + xmlViewModel = new XMLViewModel(SelectedJobEntry.SecondFilePath); + break; + } var window = OutputWindowHelper.CreateOutputWindow(Kernel, xmlViewModel, xmlViewModel.FileName); window.Show(); } @@ -218,16 +251,12 @@ namespace VECTO3GUI.ViewModel.Impl } private void DoAddJob() { - var filePath = FileDialogHelper.ShowSelectFilesDialog(false, _settings.XmlFilePathFolder); - if (filePath != null) - { - _jobs.Add(new JobEntry() - { - Filename = filePath.First(), - Selected = false, - Sorting = _jobs.Count - }); - } + var filePath = FileDialogHelper.ShowSelectFilesDialog(false, FileDialogHelper.JobFilter); + if (filePath.IsNullOrEmpty() || !IsNewJobFile(filePath.First())) + return; + + var jobEntry = SerializeHelper.DeserializeToObject<JobEntry>(filePath.First()); + _jobs.Add(jobEntry); } @@ -235,8 +264,7 @@ namespace VECTO3GUI.ViewModel.Impl { get { - return _openSettingsCommand ?? - (_openSettingsCommand = new RelayCommand(DoOpenSettingsCommand)); + return _openSettingsCommand ?? (_openSettingsCommand = new RelayCommand(DoOpenSettingsCommand)); } } private void DoOpenSettingsCommand() @@ -247,12 +275,12 @@ namespace VECTO3GUI.ViewModel.Impl window.ShowDialog(); } + public ICommand ExitMainCommand { get { - return _exitMainCommand ?? - (_exitMainCommand = new RelayCommand<Window>(DoCloseMainCommand)); + return _exitMainCommand ?? (_exitMainCommand = new RelayCommand<Window>(DoCloseMainCommand)); } } private void DoCloseMainCommand(Window window) @@ -260,139 +288,152 @@ namespace VECTO3GUI.ViewModel.Impl window?.Close(); } + public ICommand AddBusJob { get { - return _addBusJobCommand ?? - (_addBusJobCommand = new RelayCommand(DoAddBusJobCommand)); + return _addBusJobCommand ?? (_addBusJobCommand = new RelayCommand<JobType>(DoAddBusJobCommand)); } } - - private void DoAddBusJobCommand() + private void DoAddBusJobCommand(JobType jobType) { - var viewModel = new BusJobViewModel(); - var window = OutputWindowHelper.CreateOutputWindow(Kernel, viewModel, "Create Bus Job"); - window.ShowDialog(); + var viewModel = GetBusJobViewModel(jobType); + var window = CreateBusJobOutputWindow(viewModel, jobType); + if (window.ShowDialog() == true) + AddBusJobEntry(((IBusJobViewModel)viewModel)?.SavedJobEntry); } - public ICommand MoveJobUp { get { return new RelayCommand(() => { }, () => false); } } - public ICommand MoveJobDown { get { return new RelayCommand(() => { }, () => false); } } - public ICommand StartSimulation { get { return new RelayCommand(() => { }, () => false); } } - public ICommand JobEntrySetActive { get { return new RelayCommand(() => { }, () => false); } } + public ICommand MoveJobUp + { + get { return _moveJobUpCommand ?? (_moveJobUpCommand = new RelayCommand<JobEntry>(DoMoveJobUpCommand)); } + } + private void DoMoveJobUpCommand(JobEntry jobEntry) + { + if (jobEntry == null) + return; + var index = _jobs.IndexOf(jobEntry); + if (index - 1 >= 0) + _jobs.Move(index, index - 1); + } - #endregion + public ICommand MoveJobDown + { + get { return _moveJobDownCommand ?? (_moveJobDownCommand = new RelayCommand<JobEntry>(DoMoveJobDownCommand)); } + } + private void DoMoveJobDownCommand(JobEntry jobEntry) + { + if (jobEntry == null) + return; + var index = _jobs.IndexOf(jobEntry); + if (index + 1 < _jobs.Count) + _jobs.Move(index, index + 1); + } + public ICommand StartSimulation + { + get { return _startSimulationCommand ?? (_startSimulationCommand = new RelayCommand(DoStartSimulationCommand)); } + } - private IJobEditViewModel ReadJob(string jobFile) + private void DoStartSimulationCommand() { - if (jobFile == null) - return null; - var ext = Path.GetExtension(jobFile); - if (ext == Constants.FileExtensions.VectoXMLDeclarationFile) - { + } + + public ICommand OpenInFolder + { + get { return _openInFolderCommand ?? (_openInFolderCommand = new RelayCommand<JobEntry>(DoOpenInFolderCommand)); } + } - var localName = GetLocalName(jobFile); - var xmlInputReader = Kernel.Get<IXMLInputDataReader>(); - - using (var reader = XmlReader.Create(jobFile)) - { - if (localName == XMLNames.VectoPrimaryVehicleReport) - return CreatePrimaryBusVehicleViewModel(xmlInputReader.Create(reader)); - - if (localName == XMLNames.VectoInputDeclaration) - { - var readerResult = xmlInputReader.Create(reader) as IDeclarationInputDataProvider; - if(readerResult?.JobInputData.Vehicle is XMLDeclarationCompletedBusDataProviderV26) - return CreateCompleteBusVehicleViewModel(readerResult); - } + private void DoOpenInFolderCommand(JobEntry jobEntry) + { + if (jobEntry != null) { + var dirPath = Path.GetDirectoryName(jobEntry.JobEntryFilePath); + if (Directory.Exists(dirPath)) { + Process.Start("explorer.exe", dirPath); } } + } + + #endregion + + private object GetBusJobViewModel(JobType jobType, JobEntry jobEntry = null) + { + var currentJobType = jobEntry?.JobType ?? jobType; + + object viewModel = null; + + switch (currentJobType) + { + case JobType.SingleBusJob: + viewModel = jobEntry == null + ? new SingleBusJobViewModel(Kernel, jobType) + : new SingleBusJobViewModel(Kernel, jobEntry); + break; + case JobType.CompletedBusJob: + viewModel = jobEntry == null + ? new CompletedBusJobViewModel(Kernel, jobType) + : new CompletedBusJobViewModel(Kernel, jobEntry); + break; + } - return null; + return viewModel; } - private string GetLocalName(string jobFilePath) + private OutputWindow CreateBusJobOutputWindow(object viewModel, JobType jobType) { - var doc = XDocument.Load(jobFilePath); - return doc.Root?.Name.LocalName; + return OutputWindowHelper.CreateOutputWindow(Kernel, viewModel, $"Create {jobType.GetLabel()}", + 460, 200, ResizeMode.NoResize); } + private void AddBusJobEntry(JobEntry jobEntry) + { + if (jobEntry == null) + return; + _jobs.Add(jobEntry); + } + + private void ResetBusJobEntries(JobEntry jobEntry) + { + SerializeHelper.DeserializeToObject<JobEntry>(jobEntry.JobEntryFilePath); + } + + private void UpdateJobEntry(JobEntry jobEntry) + { + SerializeHelper.SerializeToFile(jobEntry.JobEntryFilePath, jobEntry); + } + + private IJobEditViewModel ReadCompletedXmlFile(JobEntry jobEntry) + { + var xmlInputReader = Kernel.Get<IXMLInputDataReader>(); + using (var reader = XmlReader.Create(jobEntry.SecondFilePath)) + { + var readerResult = xmlInputReader.Create(reader) as IDeclarationInputDataProvider; + return CreateCompleteBusVehicleViewModel(readerResult); + } + } private IJobEditViewModel CreateCompleteBusVehicleViewModel(IDeclarationInputDataProvider dataProvider) { - - - _messages.Add(new MessageEntry { + _messages.Add(new MessageEntry + { Message = "Edit File" }); return dataProvider == null ? null : new CompleteVehicleBusJobViewModel(Kernel, dataProvider); } - - private IJobEditViewModel CreatePrimaryBusVehicleViewModel(IInputDataProvider inputData) + private bool IsNewJobFile(string filePath) { - var dataProvider = inputData as IPrimaryVehicleInformationInputDataProvider; - return dataProvider == null ? null : new PrimaryVehicleBusJobViewModel(Kernel, dataProvider); + if (!_jobs.IsNullOrEmpty()) { + for (int i = 0; i < _jobs.Count; i++) { + if (_jobs[i].JobEntryFilePath == filePath) + return false; + } + } + + return true; } } - - - - #region Legacy - - //IInputDataProvider inputData = null; - //var ext = Path.GetExtension(jobFile); - //switch (ext) { - // case Constants.FileExtensions.VectoJobFile: - // inputData = JSONInputDataFactory.ReadJsonJob(jobFile); - // break; - // case Constants.FileExtensions.VectoXMLDeclarationFile: - // //ToDo - // //case Constants.FileExtensions.VectoXMLJobFile: - // inputData = Kernel.Get<IXMLInputDataReader>().CreateDeclaration(jobFile); - // break; - // default: - // throw new UnsupportedFileVersionException(jobFile); - //} - - //var retVal = CreateJobEditViewModel(inputData); - - //if (retVal == null) { - // throw new Exception("Unsupported job type"); - //} - //return retVal; - - - - //private IJobEditViewModel CreateJobEditViewModel(IInputDataProvider inputData) - //{ - // IJobEditViewModel retVal = null; - // if (inputData is JSONInputDataV2) { - // var jsoninputData = inputData as JSONInputDataV2; - // if (jsoninputData.SavedInDeclarationMode) { - // retVal = new DeclarationJobViewModel(Kernel, jsoninputData); - // } else { - // if (jsoninputData.EngineOnlyMode) { - // retVal = new EngineOnlyJobViewModel(Kernel, jsoninputData); - // } else { - // // TODO! - // } - // } - // } - // //ToDo - // //if (inputData is XMLDeclarationInputDataProvider) { - // // var declInput = inputData as IDeclarationInputDataProvider; - // // retVal = new DeclarationJobViewModel(Kernel, declInput); - // //} - // return retVal; - //} - - - #endregion - - } diff --git a/VECTO3GUI/ViewModel/Impl/MainWindowViewModel.cs b/VECTO3GUI/ViewModel/Impl/MainWindowViewModel.cs index ba6a82a500ed458ab9e9cf258943e3c509a88f0f..2b34f82b2637c1a5036c3f2e9eb1c09340a59709 100644 --- a/VECTO3GUI/ViewModel/Impl/MainWindowViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/MainWindowViewModel.cs @@ -1,19 +1,28 @@ -using System.Windows.Input; +using System.Reflection; +using System.Text.RegularExpressions; using Ninject; -using VECTO3GUI.Util; using VECTO3GUI.ViewModel.Interfaces; -using VECTO3GUI.Views; + namespace VECTO3GUI.ViewModel.Impl { public class MainWindowViewModel : ObservableObject, IMainWindowViewModel { private IMainView _currentViewModel; + private string _version; + + public string Version + { + get { return _version; } + set { SetProperty(ref _version, value); } + } + public MainWindowViewModel(IKernel kernel) { Kernel = kernel; CurrentViewModel = Kernel.Get<IJoblistViewModel>(); + SetCurrentVersionNumber(); } @@ -22,5 +31,14 @@ namespace VECTO3GUI.ViewModel.Impl get { return _currentViewModel; } set { SetProperty(ref _currentViewModel, value); } } + + private void SetCurrentVersionNumber() + { + var assembly = Assembly.ReflectionOnlyLoadFrom("VectoCommon.dll"); + var regex = new Regex(@"Version=([0-9*\.+]*),"); + var versionNumber = regex.Match(assembly.FullName).Groups[1].Value; + + Version = $"VECTO-DEV {versionNumber}-DEV"; + } } } diff --git a/VECTO3GUI/ViewModel/Impl/PrimaryVehicleBusJobViewModel.cs b/VECTO3GUI/ViewModel/Impl/PrimaryVehicleBusJobViewModel.cs index f70e430fb85658852d0bc504413224d8ec91c5c6..0d17a35448f72749292eda9e01af03713192ef39 100644 --- a/VECTO3GUI/ViewModel/Impl/PrimaryVehicleBusJobViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/PrimaryVehicleBusJobViewModel.cs @@ -25,7 +25,7 @@ namespace VECTO3GUI.ViewModel.Impl } - protected override void DoSaveJob() + protected override void DoSaveJob(Window window) { throw new NotImplementedException(); } @@ -35,7 +35,7 @@ namespace VECTO3GUI.ViewModel.Impl throw new NotImplementedException(); } - protected override void DoSaveToJob() + protected override void DoSaveToJob(Window window) { throw new NotImplementedException(); } diff --git a/VECTO3GUI/ViewModel/Impl/SingleBusJobViewModel.cs b/VECTO3GUI/ViewModel/Impl/SingleBusJobViewModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..edec0ef8f3f83a19fd120dcf89a1983e1d1f3777 --- /dev/null +++ b/VECTO3GUI/ViewModel/Impl/SingleBusJobViewModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Ninject; + +namespace VECTO3GUI.ViewModel.Impl +{ + public class SingleBusJobViewModel : AbstractBusJobViewModel + { + public SingleBusJobViewModel(IKernel kernel, JobType jobType): base(kernel, jobType) + { + SetFirstFileLabel(); + } + + public SingleBusJobViewModel(IKernel kernel, JobEntry jobEntry) : base(kernel, jobEntry) + { + SetFirstFileLabel(); + } + + protected sealed override void SetFirstFileLabel() + { + FirstLabelText = $"Select {JobFileType.PrimaryBusFile.GetLable()}"; + } + } +} diff --git a/VECTO3GUI/ViewModel/Interfaces/IAirdragViewModel.cs b/VECTO3GUI/ViewModel/Interfaces/IAirdragViewModel.cs index c018b15fb8859a4e261629e4199e339420a317be..f85fd276dd766072df66eafa7d583ee6da975e85 100644 --- a/VECTO3GUI/ViewModel/Interfaces/IAirdragViewModel.cs +++ b/VECTO3GUI/ViewModel/Interfaces/IAirdragViewModel.cs @@ -8,6 +8,10 @@ namespace VECTO3GUI.ViewModel.Interfaces { IAirdragDeclarationInputData ModelData { get; } bool IsEditable { get; } + + bool NoAirdragData { get; } + bool UseMeasurementData { get; } + ICommand LoadFileCommand { get; } ICommand AirdragConfigCommand { get; } diff --git a/VECTO3GUI/ViewModel/Interfaces/IAuxiliariesBus.cs b/VECTO3GUI/ViewModel/Interfaces/IAuxiliariesBus.cs index 1c93496d55442429ec9315eac469b8ae9f4f0b1d..2e849ec87e7c41c7912a3947ab4226e03626253e 100644 --- a/VECTO3GUI/ViewModel/Interfaces/IAuxiliariesBus.cs +++ b/VECTO3GUI/ViewModel/Interfaces/IAuxiliariesBus.cs @@ -34,5 +34,7 @@ namespace VECTO3GUI.ViewModel.Interfaces bool SeparateAirDistributionDucts { get; set; } #endregion + ConsumerTechnology DoorDriveTechnology { get; set; } + } } diff --git a/VECTO3GUI/ViewModel/Interfaces/IBusJobViewModel.cs b/VECTO3GUI/ViewModel/Interfaces/IBusJobViewModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..2af1764f52943d83f7c31eadd0f36528915f6aff --- /dev/null +++ b/VECTO3GUI/ViewModel/Interfaces/IBusJobViewModel.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using VECTO3GUI.ViewModel.Impl; + +namespace VECTO3GUI.ViewModel.Interfaces +{ + public interface IBusJobViewModel + { + JobFileType FirstFileType { get; } + JobFileType SecondFileType { get; } + string FirstFilePath { get; } + string SecondFilePath { get; } + string FirstLabelText { get; } + string SecondLabelText { get; } + JobEntry SavedJobEntry { get; } + + ICommand SelectFirstFileCommand { get; } + ICommand SelectSecondFileCommand { get; } + ICommand CancelCommand { get; } + ICommand SaveCommand { get; } + } +} diff --git a/VECTO3GUI/ViewModel/Interfaces/IJoblistViewModel.cs b/VECTO3GUI/ViewModel/Interfaces/IJoblistViewModel.cs index 4c0f44b9c7bda3d33d2b5f5f1db8e14c78c3000c..09bcf5e9d90d3b5a1735bf6ca7810ff73a63706f 100644 --- a/VECTO3GUI/ViewModel/Interfaces/IJoblistViewModel.cs +++ b/VECTO3GUI/ViewModel/Interfaces/IJoblistViewModel.cs @@ -1,12 +1,13 @@ using System.Collections.ObjectModel; using System.Windows.Input; +using VECTO3GUI.Helper; using VECTO3GUI.ViewModel.Impl; namespace VECTO3GUI.ViewModel.Interfaces { public interface IJoblistViewModel : IMainView { - ObservableCollection<JobEntry> Jobs { get; } + ObservableCollectionEx<JobEntry> Jobs { get; } ObservableCollection<MessageEntry> Messages { get; } ICommand AddBusJob { get; } ICommand AddJob { get; } @@ -16,10 +17,11 @@ namespace VECTO3GUI.ViewModel.Interfaces ICommand MoveJobDown { get; } ICommand StartSimulation { get; } ICommand EditJob { get; } - ICommand JobEntrySetActive { get; } + ICommand EditCompletedFile { get; } ICommand CreateNewJob { get; } ICommand OpenJob { get; } ICommand OpenSettings { get; } ICommand ExitMainCommand { get; } + ICommand OpenInFolder { get; } } } diff --git a/VECTO3GUI/ViewModel/Interfaces/IMainWindowViewModel.cs b/VECTO3GUI/ViewModel/Interfaces/IMainWindowViewModel.cs index 00a452eaf6f2b767f56b779ba10dde865dca8c34..c11ec181ff0b2343cb0b4f1cf3e4b6076c994515 100644 --- a/VECTO3GUI/ViewModel/Interfaces/IMainWindowViewModel.cs +++ b/VECTO3GUI/ViewModel/Interfaces/IMainWindowViewModel.cs @@ -3,5 +3,6 @@ public interface IMainWindowViewModel { IMainView CurrentViewModel { get; } + string Version { get; } } } diff --git a/VECTO3GUI/Views/BusJobView.xaml b/VECTO3GUI/Views/BusJobView.xaml index f800ed32def7437fa0ba3b5e915b6a0e547b5de0..5aeebfb8fa65873aaa94bb852f5a98c419ee3066 100644 --- a/VECTO3GUI/Views/BusJobView.xaml +++ b/VECTO3GUI/Views/BusJobView.xaml @@ -3,54 +3,97 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:local="clr-namespace:VECTO3GUI.Views" + xmlns:impl="clr-namespace:VECTO3GUI.ViewModel.Impl" + xmlns:interfaces="clr-namespace:VECTO3GUI.ViewModel.Interfaces" mc:Ignorable="d" - d:DesignHeight="200" d:DesignWidth="440"> + d:DesignHeight="200" d:DesignWidth="440" + d:DataContext="{d:DesignInstance Type=impl:AbstractBusJobViewModel, IsDesignTimeCreatable=False}"> + + <d:JoblistView.DataContext> + <x:Type Type="interfaces:IBusJobViewModel"/> + </d:JoblistView.DataContext> + <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="40"/> </Grid.RowDefinitions> - <Grid Grid.Row="0" > - <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="0"/> + <ColumnDefinition/> + <ColumnDefinition Width="10"/> + </Grid.ColumnDefinitions> - <StackPanel Orientation="Horizontal"> - <ComboBox DataContext="{Binding }"/> - </StackPanel> + <Grid Grid.Row="0" Grid.Column="1" > + <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Left"> - <TextBlock Text="Default Save Path Location: " Margin="5,0,0,0"/> + <TextBlock Text="{Binding FirstLabelText}" Width="150" Margin="5,0,0,0"/> <TextBox Width="200" Margin="0,0,5,0" IsReadOnly="True" IsReadOnlyCaretVisible="True" - Text="{Binding SavePathFolder}"/> - <Button Content="..." Width="30" - Command="{Binding OpenSaveFolderCommand}" - CommandParameter="{Binding SavePathFolder}"/> + Text="{Binding FirstFilePath}"> + + <Validation.ErrorTemplate> + <ControlTemplate> + <DockPanel> + <TextBlock Foreground="Red" DockPanel.Dock="Top" Text="{Binding ErrorContent}" /> + <AdornedElementPlaceholder/> + </DockPanel> + </ControlTemplate> + </Validation.ErrorTemplate> + + <TextBox.Style> + <Style> + <Style.Triggers> + <Trigger Property="Validation.HasError" Value="true"> + <Setter Property="Border.BorderBrush" Value="Red"/> + </Trigger> + </Style.Triggers> + </Style> + </TextBox.Style> + </TextBox> + <Button Content="..." Width="30" Margin="5,0,0,0" + Command="{Binding SelectFirstFileCommand}" + CommandParameter="{Binding FirstFileType}"/> </StackPanel> - <StackPanel Orientation="Horizontal" Margin="0,5,0,0"> - <TextBlock Text="Default XML-Files Location: " Margin="5,0,0,0"/> + <StackPanel Orientation="Horizontal" Margin="0,16,0,0"> + <TextBlock Text="{Binding SecondLabelText}" Width="150" Margin="5,0,0,0"/> <TextBox Width="200" Margin="0,0,5,0" IsReadOnly="True" IsReadOnlyCaretVisible="True" - Text="{Binding XMLFilePath}"/> - <Button Content="..." Width="30" - Command="{Binding OpenXMLFolderCommand}" - CommandParameter="{Binding XMLFilePath}"/> + Text="{Binding SecondFilePath}"> + + <Validation.ErrorTemplate> + <ControlTemplate> + <DockPanel> + <TextBlock Foreground="Red" DockPanel.Dock="Top" Text="{Binding ErrorContent}" /> + <AdornedElementPlaceholder/> + </DockPanel> + </ControlTemplate> + </Validation.ErrorTemplate> + + <TextBox.Style> + <Style> + <Style.Triggers> + <Trigger Property="Validation.HasError" Value="true"> + <Setter Property="Border.BorderBrush" Value="Red"/> + </Trigger> + </Style.Triggers> + </Style> + </TextBox.Style> + </TextBox> + <Button Content="..." Width="30" Margin="5,0,0,0" + Command="{Binding SelectSecondFileCommand }" + CommandParameter="{Binding SecondFileType}"/> </StackPanel> </StackPanel> </Grid> - <Grid Grid.Row="1"> - <Grid.ColumnDefinitions> - <ColumnDefinition/> - <ColumnDefinition/> - </Grid.ColumnDefinitions> + <Grid Grid.Row="1" Grid.Column="1"> - <Button Content="Reset" HorizontalAlignment="Left" Width="80" Margin="10,0,0,0" - Command="{Binding ResetCommand}"/> - - <StackPanel Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Right"> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <Button Content="Save" HorizontalAlignment="Right" Margin="5,0,0,0" VerticalAlignment="Center" Width="70" - Command="{Binding SaveCommand}"/> + Command="{Binding SaveCommand}" + CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/> <Button Content="Cancel" HorizontalAlignment="Right" Margin="5,0,10,0" Width="70" Command="{Binding CancelCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/> diff --git a/VECTO3GUI/Views/ComponentViews/Declaration/AirdragDeclarationView.xaml b/VECTO3GUI/Views/ComponentViews/Declaration/AirdragDeclarationView.xaml index 009760e99dc82a370a1c12929dfc0ec1f3eafdb7..9998c574ad2fdf28f5b8ba84faccb2c6eb601ff4 100644 --- a/VECTO3GUI/Views/ComponentViews/Declaration/AirdragDeclarationView.xaml +++ b/VECTO3GUI/Views/ComponentViews/Declaration/AirdragDeclarationView.xaml @@ -32,12 +32,13 @@ <StackPanel Orientation="Vertical"> <RadioButton GroupName="AirdragConfig" Margin="5" Content="{Binding Source={x:Static impl:AirdragConfig.WithoutAirdrag}, Converter={converter:EnumConverter}}" - Command="{Binding AirdragConfigCommand}" CommandParameter="{Binding Source={x:Static impl:AirdragConfig.WithoutAirdrag}}"/> + Command="{Binding AirdragConfigCommand}" CommandParameter="{Binding Source={x:Static impl:AirdragConfig.WithoutAirdrag}}" + IsChecked="{Binding NoAirdragData}"/> <RadioButton GroupName="AirdragConfig" Margin="5" Content="{Binding Source={x:Static impl:AirdragConfig.UseMeasurementData}, Converter={converter:EnumConverter}}" Command="{Binding AirdragConfigCommand}" CommandParameter="{ Binding Source={x:Static impl:AirdragConfig.UseMeasurementData}}" - IsChecked="{Binding IsEditable}"/> + IsChecked="{Binding UseMeasurementData}"/> <StackPanel Orientation="Horizontal" Margin="30,10,10,10"> <Label Content="Load Component File:"/> @@ -51,18 +52,18 @@ </GroupBox> <GroupBox Header="Aridrag Data" Width="500" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="1" Height="250" VerticalAlignment="Top" - Visibility="{Binding IsEditable, Converter={converter:BoolVisibilityConverter}}"> + Visibility="{Binding UseMeasurementData, Converter={converter:BoolVisibilityConverter}}"> <StackPanel Orientation="Vertical" Width="450" HorizontalAlignment="Left" Grid.IsSharedSizeScope="True"> <customControls:VectoParameterControl Caption="Manufacturer" Unit="" CaptionWidthGroup="vehicleLbl" UnitWidthGroup="unitWidth" - Value="{Binding Manufacturer}" IsEnabled="{Binding IsEditable}" /> + Value="{Binding Manufacturer}" IsEnabled="{Binding IsEditable, UpdateSourceTrigger=PropertyChanged}" /> <customControls:VectoParameterControl Caption="Model" Unit="" CaptionWidthGroup="vehicleLbl" UnitWidthGroup="unitWidth" - Value="{Binding Model}" IsEnabled="{Binding IsEditable}" /> + Value="{Binding Model}" IsEnabled="{Binding IsEditable, UpdateSourceTrigger=PropertyChanged}" /> <!-- <mah:DateTimePicker --> <!-- SelectedDate="{Binding Date}" --> diff --git a/VECTO3GUI/Views/ComponentViews/Declaration/CompleteVehicleBusView.xaml b/VECTO3GUI/Views/ComponentViews/Declaration/CompleteVehicleBusView.xaml index 2c4a6804415048e0d56de2a35e583a1f3e6a93be..259c5464310d942e3b737fda2798635d787c8b6c 100644 --- a/VECTO3GUI/Views/ComponentViews/Declaration/CompleteVehicleBusView.xaml +++ b/VECTO3GUI/Views/ComponentViews/Declaration/CompleteVehicleBusView.xaml @@ -8,6 +8,7 @@ xmlns:customControls="clr-namespace:VECTO3GUI.Views.CustomControls" xmlns:helper="clr-namespace:VECTO3GUI.Helper" xmlns:converter="clr-namespace:VECTO3GUI.Helper.Converter" + xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="500"> @@ -33,16 +34,19 @@ <customControls:VectoParameterControl Caption="Manufacturer" Unit="" CaptionWidthGroup="vehicleLbl" UnitWidthGroup="unitWidth" - Value="{Binding Manufacturer}" /> + Value="{Binding Manufacturer}" > + </customControls:VectoParameterControl> + <customControls:VectoParameterControl Caption="Manufacturer Address" Unit="" CaptionWidthGroup="vehicleLbl" UnitWidthGroup="unitWidth" Value="{Binding ManufacturerAddress}" /> <customControls:VectoParameterControl Caption="VIN" Unit="" CaptionWidthGroup="vehicleLbl" UnitWidthGroup="unitWidth" Value="{Binding VIN}" /> - <customControls:VectoParameterControl + + <!--<customControls:VectoParameterControl Caption="Date" Unit="" CaptionWidthGroup="vehicleLbl" UnitWidthGroup="unitWidth" - Value="{Binding Date}" /> + Value="{Binding Date}" />--> <customControls:ComboParameter Caption="Legislative Class" diff --git a/VECTO3GUI/Views/CustomControls/VectoParameterControl.xaml b/VECTO3GUI/Views/CustomControls/VectoParameterControl.xaml index cc602f30f1093f24a6d8609500de7d056d8b9f73..d5d86f796583a7d3c47836d74a0840012196b3ee 100644 --- a/VECTO3GUI/Views/CustomControls/VectoParameterControl.xaml +++ b/VECTO3GUI/Views/CustomControls/VectoParameterControl.xaml @@ -4,6 +4,8 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:customControls="clr-namespace:VECTO3GUI.Views.CustomControls" + xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" + xmlns:helper="clr-namespace:VECTO3GUI.Helper" mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="300" d:DataContext="{d:DesignInstance {x:Type customControls:VectoParameterControl}}"> <Grid Margin="5"> @@ -18,7 +20,11 @@ <TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Caption}" Margin="0,0,10,0"/> <TextBox Grid.Row="0" Grid.Column="1" Margin="20,0,0,0" Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" - TextAlignment="{Binding ValueAlign}"/> - <TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding Unit}" Margin="5,0,5,0"/> + TextAlignment="{Binding ValueAlign}"> + <!--<i:Interaction.Behaviors> + <helper:TextBoxInputRegExBehaviour RegularExpression="^\d+$" MaxLength="9" EmptyValue="0" /> + </i:Interaction.Behaviors>--> + </TextBox> + <TextBlock Grid.Row="0" Grid.Column="2" Text="{Binding Unit}" Margin="5,0,5,0"/> </Grid> </UserControl> diff --git a/VECTO3GUI/Views/JoblistTabView.xaml b/VECTO3GUI/Views/JoblistTabView.xaml index 87664c951cfceb097cca296f0bf8f5fee8061890..f5391b0b561d4f8594d818f793509b59acab96da 100644 --- a/VECTO3GUI/Views/JoblistTabView.xaml +++ b/VECTO3GUI/Views/JoblistTabView.xaml @@ -7,12 +7,15 @@ xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:converter="clr-namespace:VECTO3GUI.Helper.Converter" mc:Ignorable="d" - d:DesignHeight="450" d:DesignWidth="800"> + d:DesignHeight="450" d:DesignWidth="800" + xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro" + xmlns:interfaces="clr-namespace:VECTO3GUI.ViewModel.Interfaces" + Dialog:DialogParticipation.Register="{Binding}"> - <!--<d:JoblistTabView.DataContext> + <d:JoblistTabView.DataContext> <x:Type Type="interfaces:IJobEditViewModel"/> - </d:JoblistTabView.DataContext>--> + </d:JoblistTabView.DataContext> <Grid> @@ -26,10 +29,13 @@ <StackPanel Orientation="Vertical"> <Menu> <MenuItem Header="File"> - <MenuItem Header="Save" Command="{Binding SaveJob}"/> + <MenuItem Header="Save" + Command="{Binding SaveJob}" + CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/> <MenuItem Header="Save to" Command="{Binding SaveToJob}"/> <Separator HorizontalAlignment="Stretch" Background="Gray"/> - <MenuItem Header="Exit" Command="{Binding CloseJob}" + <MenuItem Header="Exit" + Command="{Binding CloseJob}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/> </MenuItem> </Menu> diff --git a/VECTO3GUI/Views/JoblistView.xaml b/VECTO3GUI/Views/JoblistView.xaml index 2c20a766c37c5aaf73caf3c7d641b513a9e0cf9f..8cc63c9467189b5db115e826fec105a9ddb97036 100644 --- a/VECTO3GUI/Views/JoblistView.xaml +++ b/VECTO3GUI/Views/JoblistView.xaml @@ -3,12 +3,10 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:viewModel="clr-namespace:VECTO3GUI.ViewModel" - xmlns:helper="clr-namespace:VECTO3GUI.Helper" xmlns:impl="clr-namespace:VECTO3GUI.ViewModel.Impl" xmlns:interfaces="clr-namespace:VECTO3GUI.ViewModel.Interfaces" xmlns:views="clr-namespace:VECTO3GUI.Views" - xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="600" d:DataContext="{d:DesignInstance Type=impl:JoblistViewModel, IsDesignTimeCreatable=False}"> @@ -19,9 +17,9 @@ <Grid> <Grid.ColumnDefinitions> - <ColumnDefinition Width="30"/> - <ColumnDefinition/> <ColumnDefinition Width="80"/> + <ColumnDefinition/> + <ColumnDefinition Width="150"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="30"/> @@ -31,38 +29,97 @@ </Grid.RowDefinitions> + <Grid Grid.Row="1" Grid.Column="0"> + + <StackPanel Orientation="Vertical"> + <Button VerticalAlignment="Top" Margin="10,10,0,0"> + <StackPanel Orientation="Horizontal"> + <iconPacks:PackIconModern Width="20" Height="15" Kind="ControlPlay" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Green"/> + <TextBlock Text="Start " /> + </StackPanel> + </Button> + + <StackPanel Orientation="Vertical" HorizontalAlignment="Right" Margin="0,10,0,0"> + <Button Width="25" + Command="{Binding MoveJobUp}" + CommandParameter="{Binding ElementName=JobList, Path=SelectedItem}"> + <StackPanel Orientation="Horizontal"> + <iconPacks:PackIconModern Width="15" Height="15" Kind="ArrowUp" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Green"/> + </StackPanel> + </Button> + + <Button Width="25" Margin="0,5,0,0" + Command="{Binding MoveJobDown}" + CommandParameter="{Binding ElementName=JobList, Path=SelectedItem}"> + <StackPanel Orientation="Horizontal"> + <iconPacks:PackIconModern Width="15" Height="15" Kind="ArrowDown" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Green"/> + </StackPanel> + </Button> + </StackPanel> + </StackPanel> + </Grid> <Grid Grid.Row="1" Grid.Column="1" Margin="10"> - <DataGrid ItemsSource="{Binding Jobs}" + <DataGrid x:Name="JobList" ItemsSource="{Binding Jobs}" SelectedValue="{Binding DataContext.SelectedJobEntry, RelativeSource={RelativeSource AncestorType=views:JoblistView}}" Style="{DynamicResource AzureDataGrid}" BorderThickness="1" CanUserAddRows="False" AutoGenerateColumns="False" SelectionUnit="FullRow" - IsReadOnly="True" HeadersVisibility="All" RowHeaderWidth="5" > + IsReadOnly="False" HeadersVisibility="All" RowHeaderWidth="5" > <DataGrid.Resources> <ContextMenu x:Key="RowMenu"> - <MenuItem Header="View File" Command="{Binding DataContext.OpenJob, RelativeSource={RelativeSource AncestorType=views:JoblistView}}"/> - <MenuItem Header="Edit File" Command="{Binding DataContext.EditJob, RelativeSource={RelativeSource AncestorType=views:JoblistView}}"/> + <MenuItem Header="{Binding DataContext.FirstContextMenu, RelativeSource={RelativeSource AncestorType=views:JoblistView}}" + Command="{Binding DataContext.OpenJob, RelativeSource={RelativeSource AncestorType=views:JoblistView}}" + CommandParameter="{Binding Source={x:Static impl:JobFileType.PrimaryBusFile}}"/> + <MenuItem Header="View Completed Bus File" + Command="{Binding DataContext.OpenJob, RelativeSource={RelativeSource AncestorType=views:JoblistView}}" + CommandParameter="{Binding Source={x:Static impl:JobFileType.CompletedBusFile}}"/> + + <Separator HorizontalAlignment="Stretch" Background="Gray"/> + + <MenuItem Header="Edit Job" + Command="{Binding DataContext.EditJob, RelativeSource={RelativeSource AncestorType=views:JoblistView}}" + CommandParameter="{Binding DataContext.SelectedJobEntry, RelativeSource={RelativeSource AncestorType=views:JoblistView}}"/> + <MenuItem Header="Edit Completed File" + Command="{Binding DataContext.EditCompletedFile, RelativeSource={RelativeSource AncestorType=views:JoblistView}}" + CommandParameter="{Binding DataContext.SelectedJobEntry, RelativeSource={RelativeSource AncestorType=views:JoblistView}}"/> + + <Separator HorizontalAlignment="Stretch" Background="Gray"/> + + <MenuItem Header="Show In Folder" + Command="{Binding DataContext.OpenInFolder, RelativeSource={RelativeSource AncestorType=views:JoblistView}}" + CommandParameter="{Binding DataContext.SelectedJobEntry, RelativeSource={RelativeSource AncestorType=views:JoblistView}}"/> + <Separator HorizontalAlignment="Stretch" Background="Gray"/> - <MenuItem Header="Remove File" Command="{Binding DataContext.RemoveJob, RelativeSource={RelativeSource AncestorType=views:JoblistView}}"/> + + <MenuItem Header="Remove Job" + Command="{Binding DataContext.RemoveJob, RelativeSource={RelativeSource AncestorType=views:JoblistView}}" + CommandParameter="{Binding DataContext.SelectedJobEntry, RelativeSource={RelativeSource AncestorType=views:JoblistView}}"/> </ContextMenu> </DataGrid.Resources> <DataGrid.ContextMenu> <ContextMenu> - <MenuItem Header="Add File" Command="{Binding AddJob}"/> - <MenuItem Header="New File" Command="{Binding CreateNewJob}"/> + <MenuItem Header="Add Job" Command="{Binding AddJob}"/> + <Separator HorizontalAlignment="Stretch" Background="Gray"/> + <MenuItem Header="Create Single Bus Job" + Command="{Binding AddBusJob}" CommandParameter="{Binding Source={x:Static impl:JobType.SingleBusJob}}"/> + <MenuItem Header="Create Completed Bus Job" + Command="{Binding AddBusJob}" CommandParameter="{Binding Source={x:Static impl:JobType.CompletedBusJob}}"/> + <MenuItem Header="Create Completed XML" + Command="{Binding CreateNewJob}"/> <Separator HorizontalAlignment="Stretch" Background="Gray"/> <MenuItem Header="Remove All" Command="{Binding RemoveAllJobs}"/> </ContextMenu> </DataGrid.ContextMenu> <DataGrid.Columns> - <DataGridTextColumn Header="File Path" Binding="{Binding Filename}" > + <DataGridCheckBoxColumn Binding="{Binding Selected, UpdateSourceTrigger=PropertyChanged}" /> + <DataGridTextColumn Header="File Path" Binding="{Binding JobEntryFilePath}" IsReadOnly="True"> <DataGridTextColumn.CellStyle> <Style TargetType= "{x:Type DataGridCell}" BasedOn="{StaticResource MetroDataGridCell}" > <Setter Property="ContextMenu" Value="{StaticResource RowMenu}"/> - <Setter Property="HorizontalAlignment" Value="Stretch"></Setter> + <Setter Property="HorizontalAlignment" Value="Stretch"/> </Style> </DataGridTextColumn.CellStyle> </DataGridTextColumn> @@ -73,15 +130,25 @@ </Grid> <Grid Grid.Row="1" Grid.Column="2" Margin="0,0,10,0"> - <StackPanel Orientation="Vertical" Margin="0,30,0,0"> - <Button Margin="0,5,0,0" Command="{Binding AddBusJob}" Content="Add Bus Job"/> - <Button Margin="0,5,0,0" Command="{Binding EditJob}" Content="Edit File" /> - <Button Margin="0,5,0,0" Command="{Binding CreateNewJob}" Content="New File" /> - <Button Margin="0,5,0,0" Command="{Binding RemoveJob}" Content="Remove File" /> + <StackPanel Orientation="Vertical" Margin="0,30,0,0" Width="105"> + <Button Margin="0,5,0,0" Content="Add Job" + Command="{Binding AddJob}"/> + + <Button Margin="0,5,0,0" Content="Edit Job" + Command="{Binding EditJob}" + CommandParameter="{Binding ElementName=JobList, Path=SelectedItem}"/> + + <Button Margin="0,5,0,0" Content="Remove Job" + Command="{Binding RemoveJob}" + CommandParameter="{Binding ElementName=JobList, Path=SelectedItem}"/> + + <Button Margin="0,5,0,0" Content="Edit Completed File" + Command="{Binding EditCompletedFile}" + CommandParameter="{Binding ElementName=JobList, Path=SelectedItem}"/> </StackPanel> </Grid> - <Grid Grid.Row="2" Grid.ColumnSpan="3" Margin="10,20,20,10"> + <Grid Grid.Row="2" Grid.ColumnSpan="3" Grid.Column="0" Margin="10,20,20,10"> <DataGrid ItemsSource="{Binding Messages}" BorderThickness="1" CanUserAddRows="False" AutoGenerateColumns="False" SelectionUnit="FullRow" IsReadOnly="True" HeadersVisibility="All" RowHeaderWidth="5"> @@ -92,14 +159,7 @@ </DataGrid.Columns> </DataGrid> - </Grid> </Grid> - - - - - - </UserControl> diff --git a/VECTO3GUI/Views/OutputWindow.xaml b/VECTO3GUI/Views/OutputWindow.xaml index 8bad3430b2c056566be50497e7d057a093095a78..e81d0b388d0fca3afff9ae36a1c18ea005ed89b3 100644 --- a/VECTO3GUI/Views/OutputWindow.xaml +++ b/VECTO3GUI/Views/OutputWindow.xaml @@ -8,6 +8,8 @@ xmlns:impl="clr-namespace:VECTO3GUI.ViewModel.Impl" xmlns:interfaces="clr-namespace:VECTO3GUI.ViewModel.Interfaces" xmlns:converters="http://metro.mahapps.com/winfx/xaml/shared" + xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" + xmlns:helper="clr-namespace:VECTO3GUI.Helper" mc:Ignorable="d" Title="{Binding WindowTitle}" Height="450" Width="800" WindowStartupLocation="CenterScreen" TitleCharacterCasing="Normal" d:DataContext="{d:DesignInstance Type=impl:OutputWindowViewModel, IsDesignTimeCreatable=False}"> @@ -32,7 +34,7 @@ </Grid.RowDefinitions> <Grid Grid.Row="0"> - <ContentControl Content="{Binding ViewModel}" /> + <ContentControl Content="{Binding ViewModel}" /> </Grid> <Grid Grid.Row="1"> @@ -40,4 +42,10 @@ </Grid> </Grid> + <i:Interaction.Triggers> + <i:EventTrigger EventName="Closing"> + <helper:EventCommandExecuter Command="{Binding Path=ViewModel.CloseWindowCommand, Mode=OneTime}"/> + </i:EventTrigger> + </i:Interaction.Triggers> + </mah:MetroWindow> diff --git a/VECTO3GUI/packages.config b/VECTO3GUI/packages.config index bc9ede5301f91b9952915cf8cc74cb8edf431896..2cb8134ec1dc64efe357691771c6a8486048fce7 100644 --- a/VECTO3GUI/packages.config +++ b/VECTO3GUI/packages.config @@ -5,6 +5,7 @@ <package id="ControlzEx" version="3.0.2.4" targetFramework="net452" /> <package id="MahApps.Metro" version="1.6.5" targetFramework="net452" /> <package id="MahApps.Metro.IconPacks" version="3.7.0" targetFramework="net452" /> + <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net452" /> <package id="Ninject" version="3.3.4" targetFramework="net452" /> <package id="Ninject.Extensions.Factory" version="3.3.2" targetFramework="net452" /> <package id="System.Windows.Interactivity.WPF" version="2.0.20525" targetFramework="net452" />