diff --git a/VECTO3GUI/Helper/FileDialogHelper.cs b/VECTO3GUI/Helper/FileDialogHelper.cs index 9ca61b169232367db5739dcd1d566d3ef4139d36..dac95a213f7fe5b43bde02b98a5e86595eb06488 100644 --- a/VECTO3GUI/Helper/FileDialogHelper.cs +++ b/VECTO3GUI/Helper/FileDialogHelper.cs @@ -13,6 +13,9 @@ namespace VECTO3GUI.Helper { public static class FileDialogHelper { + public const string XMLExtension = ".xml"; + public const string JobFileExtension = ".vecto"; + public const string XMLFilter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*"; public const string JobFilter = "Vecto Files (*.vecto|*.vecto|All Files (*.*)|*.*"; diff --git a/VECTO3GUI/MainWindow.xaml b/VECTO3GUI/MainWindow.xaml index fccc5f76bc252becc04155f13d5441834090aa55..01a895cf106f2cb51ab8013f5e9dd4b747f7a217 100644 --- a/VECTO3GUI/MainWindow.xaml +++ b/VECTO3GUI/MainWindow.xaml @@ -26,7 +26,7 @@ <Menu IsMainMenu="True" Style="{DynamicResource MetroMenu}"> <MenuItem Header="File" VerticalAlignment="Center"> - <MenuItem Header="Add Job" Command="{Binding CurrentViewModel.AddJob}"/> + <MenuItem Header="Add File" Command="{Binding CurrentViewModel.AddJob}"/> <MenuItem Header="Edit Job" Command="{Binding CurrentViewModel.EditJob}" CommandParameter="{Binding CurrentViewModel.SelectedJobEntry}"/> diff --git a/VECTO3GUI/Model/JobListModel.cs b/VECTO3GUI/Model/JobListModel.cs index 511572795cd29eebdababe85e31b83974283a7ba..cd5f825bdb216cb0e3ee91ec466e5cc5efe32032 100644 --- a/VECTO3GUI/Model/JobListModel.cs +++ b/VECTO3GUI/Model/JobListModel.cs @@ -9,6 +9,7 @@ namespace VECTO3GUI.Model { public class JobListEntry { + public string JobTypeName { get; set; } public bool IsSelected { get; set; } public string JobFilePath { get; set; } } @@ -30,7 +31,8 @@ namespace VECTO3GUI.Model private void SetConfigFolder() { - if (!Directory.Exists($"./{ConfigFolderName}")) { + if (!Directory.Exists($"./{ConfigFolderName}")) + { Directory.CreateDirectory($"{ConfigFolderName}"); } } @@ -42,13 +44,13 @@ namespace VECTO3GUI.Model 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) @@ -62,13 +64,14 @@ namespace VECTO3GUI.Model ( new JobListEntry { + JobTypeName = jobEntries[i].Header.JobType.GetLabel(), IsSelected = jobEntries[i].Selected, JobFilePath = jobEntries[i].JobEntryFilePath } ); } } - + public IList<JobEntry> GetJobEntries() { var jobEntries = new List<JobEntry>(); @@ -76,15 +79,32 @@ namespace VECTO3GUI.Model if (JobList.IsNullOrEmpty()) return jobEntries; - for (int i = 0; i < JobList.Count; i++) { - var jobEntry = SerializeHelper.DeserializeToObject<JobEntry>(JobList[i].JobFilePath); + for (int i = 0; i < JobList.Count; i++) + { + var jobType = JobTypeHelper.Parse(JobList[i].JobTypeName); + JobEntry jobEntry; + + if (jobType == JobType.CompletedBusJob || jobType == JobType.SingleBusJob) + { + jobEntry = SerializeHelper.DeserializeToObject<JobEntry>(JobList[i].JobFilePath); + } + else + { + jobEntry = new JobEntry + { + Header = new JobHeader { JobType = jobType}, + Body = new JobBody { + CompletedVehicle = JobType.CompletedXml == jobType ? JobList[i].JobFilePath : null + } + }; + } + if (jobEntry != null) { jobEntry.JobEntryFilePath = JobList[i].JobFilePath; jobEntry.Selected = JobList[i].IsSelected; jobEntries.Add(jobEntry); } } - return jobEntries; } } diff --git a/VECTO3GUI/ViewModel/Impl/CompleteVehicleBusViewModel.cs b/VECTO3GUI/ViewModel/Impl/CompleteVehicleBusViewModel.cs index 486296cb019ebc1f737560107ca1f52fc336f7f6..f6fa37164c6b5577d4064a407574c0808190a20f 100644 --- a/VECTO3GUI/ViewModel/Impl/CompleteVehicleBusViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/CompleteVehicleBusViewModel.cs @@ -288,7 +288,7 @@ namespace VECTO3GUI.ViewModel.Impl VehicleLength = vehicle.Length; VehicleWidth = vehicle.Width; EntranceHeight = vehicle.EntranceHeight; - DoorDriveTechnology = ((XMLDeclarationCompletedBusDataProviderV26)vehicle).DoorDriveTechnology; + DoorDriveTechnology = vehicle.DoorDriveTechnology; _componentData = new VehicleBusComponentData(this); ClearChangedProperties(); diff --git a/VECTO3GUI/ViewModel/Impl/JobEntry.cs b/VECTO3GUI/ViewModel/Impl/JobEntry.cs index cc789f352590c68d4a8c82d22bf46305d6c1c943..9133591f3b5e3970009aea6530ede0c5d5baca68 100644 --- a/VECTO3GUI/ViewModel/Impl/JobEntry.cs +++ b/VECTO3GUI/ViewModel/Impl/JobEntry.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using Newtonsoft.Json; @@ -8,6 +9,7 @@ namespace VECTO3GUI.ViewModel.Impl { SingleBusJob, CompletedBusJob, + CompletedXml, Unknown } @@ -15,6 +17,7 @@ namespace VECTO3GUI.ViewModel.Impl { private const string SingleBusJobLabel = "Single Bus Job"; private const string CompletedBusJobLabel = "Completed Bus Job"; + private const string CompletedXmlLabel = "Completed Bus XML"; public static string GetLabel(this JobType jobType) { @@ -24,8 +27,10 @@ namespace VECTO3GUI.ViewModel.Impl return SingleBusJobLabel; case JobType.CompletedBusJob: return CompletedBusJobLabel; + case JobType.CompletedXml: + return CompletedXmlLabel; default: - return string.Empty; + return nameof(JobType.Unknown); } } @@ -35,6 +40,9 @@ namespace VECTO3GUI.ViewModel.Impl return JobType.SingleBusJob; if (CompletedBusJobLabel == jobTypeName) return JobType.CompletedBusJob; + if (CompletedXmlLabel == jobTypeName) + return JobType.CompletedXml; + return JobType.Unknown; } @@ -88,6 +96,20 @@ namespace VECTO3GUI.ViewModel.Impl get { return _body; } set { SetProperty(ref _body, value); } } + + public string GetAbsoluteFilePath(string propertyFilePath) + { + if (IsFileName(propertyFilePath)) { + var folderPath = Path.GetDirectoryName(JobEntryFilePath); + return Path.Combine(folderPath, propertyFilePath); + } + return propertyFilePath; + } + + private bool IsFileName(string filePath) + { + return !Directory.Exists(filePath) && !File.Exists(filePath); + } } diff --git a/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs b/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs index 88f82773cd5962197826f596d54b09f1d1d3c2a0..a7d8cf6461b43c529ab394adac67f4ad35127e5f 100644 --- a/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs @@ -13,6 +13,7 @@ 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.Util; using VECTO3GUI.ViewModel.Interfaces; using VECTO3GUI.Helper; @@ -33,6 +34,8 @@ namespace VECTO3GUI.ViewModel.Impl private JobEntry _selectedJobEntry; private JobListModel _jobListModel; + private bool _visibilityFirstView; + private bool _visibilitySecView; private ICommand _newJobCommand; private ICommand _editJobCommand; @@ -59,13 +62,10 @@ namespace VECTO3GUI.ViewModel.Impl get { return _selectedJobEntry; } set { - SetProperty(ref _selectedJobEntry, value); - if (_selectedJobEntry != null) - { - var firstJobTyp = _selectedJobEntry.Header.JobType == JobType.SingleBusJob - ? JobFileType.PrimaryBusFile - : JobFileType.PIFBusFile; - FirstContextMenu = $"View {firstJobTyp.GetLable()}"; + if (SetProperty(ref _selectedJobEntry, value)) { + if(_selectedJobEntry == null) + return; + SetXmlViewBehavior(); } } } @@ -76,8 +76,6 @@ namespace VECTO3GUI.ViewModel.Impl set { SetProperty(ref _jobs, value); } } - - public ObservableCollection<MessageEntry> Messages { get { return _messages; } @@ -88,6 +86,19 @@ namespace VECTO3GUI.ViewModel.Impl get { return _firstContextMenu; } set { SetProperty(ref _firstContextMenu, value); } } + + public bool VisibilityFirstView + { + get { return _visibilityFirstView; } + set { SetProperty(ref _visibilityFirstView, value); } + } + + public bool VisibilitySecView + { + get { return _visibilitySecView; } + set { SetProperty(ref _visibilitySecView, value); } + } + #endregion @@ -103,6 +114,8 @@ namespace VECTO3GUI.ViewModel.Impl _jobs = new ObservableCollectionEx<JobEntry>(_jobListModel.GetJobEntries()); _jobs.CollectionChanged += JobsCollectionChanged; _jobs.CollectionItemChanged += JobItemChanged; + VisibilityFirstView = true; + VisibilitySecView = true; } private void JobItemChanged(object sender, PropertyChangedEventArgs e) @@ -133,7 +146,7 @@ namespace VECTO3GUI.ViewModel.Impl } private void DoDoubleClick(JobEntry jobEntry) { - if (!CanEditCompletdFile(jobEntry)) + if (jobEntry == null || !IsJobFile(jobEntry.JobEntryFilePath)) return; DoEditJob(jobEntry); } @@ -155,7 +168,7 @@ namespace VECTO3GUI.ViewModel.Impl return jobEntry != null; } - + public ICommand RemoveAllJobs { get @@ -179,7 +192,7 @@ namespace VECTO3GUI.ViewModel.Impl } private bool CanEditJob(JobEntry jobEntry) { - return jobEntry != null; + return jobEntry != null && IsJobEntry(jobEntry); } private void DoEditJob(JobEntry jobEntry) { @@ -202,7 +215,9 @@ namespace VECTO3GUI.ViewModel.Impl } private bool CanEditCompletdFile(JobEntry jobEntry) { - return jobEntry != null; + return jobEntry != null && + (IsJobEntry(jobEntry) || jobEntry.Header.JobType == JobType.CompletedXml); + } private void DoEditCompletedFile(JobEntry jobEntry) { @@ -213,8 +228,7 @@ namespace VECTO3GUI.ViewModel.Impl var window = OutputWindowHelper.CreateOutputWindow(Kernel, viewModel); window.Show(); } - - + public ICommand CreateNewJob { @@ -244,18 +258,32 @@ namespace VECTO3GUI.ViewModel.Impl return; XMLViewModel xmlViewModel = null; + var jobType = _selectedJobEntry.Header.JobType; - switch (jobFileType) { + switch (jobFileType) + { case JobFileType.PIFBusFile: case JobFileType.PrimaryBusFile: - xmlViewModel = new XMLViewModel(SelectedJobEntry.Body.PrimaryVehicle); + if (jobType == JobType.CompletedXml || jobType == JobType.Unknown && + IsXmlFile(_selectedJobEntry.JobEntryFilePath)) + { + xmlViewModel = new XMLViewModel(SelectedJobEntry.JobEntryFilePath); + } + else if (IsJobFile(_selectedJobEntry.JobEntryFilePath)) + xmlViewModel = new XMLViewModel( + SelectedJobEntry.GetAbsoluteFilePath(SelectedJobEntry.Body.PrimaryVehicle)); break; case JobFileType.CompletedBusFile: - xmlViewModel = new XMLViewModel(SelectedJobEntry.Body.CompletedVehicle); + xmlViewModel = new XMLViewModel( + SelectedJobEntry.GetAbsoluteFilePath(SelectedJobEntry.Body.CompletedVehicle)); break; } - var window = OutputWindowHelper.CreateOutputWindow(Kernel, xmlViewModel, xmlViewModel.FileName); - window.Show(); + + if (xmlViewModel != null) + { + var window = OutputWindowHelper.CreateOutputWindow(Kernel, xmlViewModel, xmlViewModel.FileName); + window.Show(); + } } @@ -272,11 +300,30 @@ namespace VECTO3GUI.ViewModel.Impl if (filePath.IsNullOrEmpty() || !IsNewJobFile(filePath.First())) return; - var jobEntry = SerializeHelper.DeserializeToObject<JobEntry>(filePath.First()); - jobEntry.JobEntryFilePath = filePath.First(); - _jobs.Add(jobEntry); + if (IsJobFile(filePath.First())) + { + var jobEntry = SerializeHelper.DeserializeToObject<JobEntry>(filePath.First()); + jobEntry.JobEntryFilePath = filePath.First(); + _jobs.Add(jobEntry); + } + else if(IsXmlFile(filePath.First())) + { + var jobEntry = GetAdditionalJobEntry(filePath.First()); + _jobs.Add(jobEntry); + } } + private bool IsJobFile(string filePath) + { + var extension = Path.GetExtension(filePath)?.ToLower(); + if (extension == FileDialogHelper.JobFileExtension) + return true; + if (extension == FileDialogHelper.XMLExtension) + return false; + + return false; + } + public ICommand OpenSettings { @@ -335,7 +382,7 @@ namespace VECTO3GUI.ViewModel.Impl if (index - 1 >= 0) _jobs.Move(index, index - 1); } - + public ICommand MoveJobDown { get { return _moveJobDownCommand ?? (_moveJobDownCommand = new RelayCommand<JobEntry>(DoMoveJobDownCommand)); } @@ -348,7 +395,7 @@ namespace VECTO3GUI.ViewModel.Impl if (index + 1 < _jobs.Count) _jobs.Move(index, index + 1); } - + public ICommand StartSimulation { @@ -375,7 +422,7 @@ namespace VECTO3GUI.ViewModel.Impl } } } - + #endregion @@ -402,12 +449,57 @@ namespace VECTO3GUI.ViewModel.Impl return viewModel; } + private JobEntry GetAdditionalJobEntry(string filePath) + { + var isCompletedBusXml = IsCompletedBusXml(filePath); + + return new JobEntry + { + JobEntryFilePath = filePath, + Header = new JobHeader + { + JobType = isCompletedBusXml ? JobType.CompletedXml : JobType.Unknown + }, + Body = new JobBody + { + CompletedVehicle = isCompletedBusXml ? filePath : null + } + }; + } + + + private bool IsCompletedBusXml(string filePath) + { + if (!File.Exists(filePath)) + 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 (inputData.JobInputData.Vehicle is XMLDeclarationCompletedBusDataProviderV26) + { + return true; + } + } + } + + return false; + } + + private OutputWindow CreateBusJobOutputWindow(object viewModel, JobType jobType) { return OutputWindowHelper.CreateOutputWindow(Kernel, viewModel, $"Create {jobType.GetLabel()}", 460, 200, ResizeMode.NoResize); } - + private void AddBusJobEntry(JobEntry jobEntry) { if (jobEntry == null) @@ -436,30 +528,28 @@ namespace VECTO3GUI.ViewModel.Impl } _jobListModel.SaveJobList(_jobs); } - + private IJobEditViewModel ReadCompletedXmlFile(JobEntry jobEntry) { var xmlInputReader = Kernel.Get<IXMLInputDataReader>(); - using (var reader = XmlReader.Create(jobEntry.Body.CompletedVehicle)) + using (var reader = XmlReader.Create(jobEntry.GetAbsoluteFilePath(jobEntry.Body.CompletedVehicle))) { var readerResult = xmlInputReader.Create(reader) as IDeclarationInputDataProvider; return CreateCompleteBusVehicleViewModel(readerResult); } } - + private IJobEditViewModel CreateCompleteBusVehicleViewModel(IDeclarationInputDataProvider dataProvider) { - _messages.Add(new MessageEntry - { - Message = "Edit File" - }); return dataProvider == null ? null : new CompleteVehicleBusJobViewModel(Kernel, dataProvider); } private bool IsNewJobFile(string filePath) { - if (!_jobs.IsNullOrEmpty()) { - for (int i = 0; i < _jobs.Count; i++) { + if (!_jobs.IsNullOrEmpty()) + { + for (int i = 0; i < _jobs.Count; i++) + { if (_jobs[i].JobEntryFilePath == filePath) return false; } @@ -467,5 +557,45 @@ namespace VECTO3GUI.ViewModel.Impl return true; } + + private bool IsJobEntry(JobEntry jobEntry) + { + return jobEntry.Header.JobType == JobType.CompletedBusJob || + jobEntry.Header.JobType == JobType.SingleBusJob; + } + + private bool IsXmlFile(string filePath) + { + if (!File.Exists(filePath)) + return false; + + return Path.GetExtension(filePath)?.ToLower() == FileDialogHelper.XMLExtension; + } + + private void SetXmlViewBehavior() + { + var isJobEntry = IsJobEntry(_selectedJobEntry); + var contextMenuText = string.Empty; + + VisibilityFirstView = true; + + if (isJobEntry) + { + VisibilitySecView = true; + + contextMenuText = _selectedJobEntry.Header.JobType == JobType.SingleBusJob + ? JobFileType.PrimaryBusFile.GetLable() + : JobFileType.PIFBusFile.GetLable(); + } + else if (IsXmlFile(_selectedJobEntry.JobEntryFilePath)) + { + + VisibilitySecView = false; + contextMenuText = _selectedJobEntry.Header.JobType == JobType.CompletedXml + ? JobType.CompletedXml.GetLabel() : "XML-File"; + } + + FirstContextMenu = $"View {contextMenuText}"; + } } } diff --git a/VECTO3GUI/Views/JoblistView.xaml b/VECTO3GUI/Views/JoblistView.xaml index aef6a140c9acb615e0834e1a634d6da4a71f9951..d6fdaa9b7fd51fbf0c7d21498addbe9dfabf641b 100644 --- a/VECTO3GUI/Views/JoblistView.xaml +++ b/VECTO3GUI/Views/JoblistView.xaml @@ -7,8 +7,9 @@ xmlns:interfaces="clr-namespace:VECTO3GUI.ViewModel.Interfaces" xmlns:views="clr-namespace:VECTO3GUI.Views" xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks" + xmlns:converter="clr-namespace:VECTO3GUI.Helper.Converter" mc:Ignorable="d" - d:DesignHeight="300" d:DesignWidth="600" + d:DesignHeight="400" d:DesignWidth="600" d:DataContext="{d:DesignInstance Type=impl:JoblistViewModel, IsDesignTimeCreatable=False}"> <d:JoblistView.DataContext> @@ -79,10 +80,14 @@ <ContextMenu x:Key="RowMenu"> <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}}"/> + CommandParameter="{Binding Source={x:Static impl:JobFileType.PrimaryBusFile}}" + Visibility="{Binding DataContext.VisibilityFirstView, Converter={converter:BoolVisibilityConverter}, + RelativeSource={RelativeSource AncestorType=views:JoblistView}}"/> <MenuItem Header="View Completed Bus File" Command="{Binding DataContext.OpenJob, RelativeSource={RelativeSource AncestorType=views:JoblistView}}" - CommandParameter="{Binding Source={x:Static impl:JobFileType.CompletedBusFile}}"/> + CommandParameter="{Binding Source={x:Static impl:JobFileType.CompletedBusFile}}" + Visibility="{Binding DataContext.VisibilitySecView, Converter={converter:BoolVisibilityConverter}, + RelativeSource={RelativeSource AncestorType=views:JoblistView}}"/> <Separator HorizontalAlignment="Stretch" Background="Gray"/> @@ -140,7 +145,7 @@ <Grid Grid.Row="1" Grid.Column="2" Margin="0,0,10,0"> <StackPanel Orientation="Vertical" Margin="0,30,0,0" Width="105"> - <Button Margin="0,5,0,0" Content="Add Job" + <Button Margin="0,5,0,0" Content="Add File" Command="{Binding AddJob}"/> <Button Margin="0,5,0,0" Content="Edit Job"