/// <summary> /// Generates .apsimx files for each child model under a given model. /// Returns false if errors were encountered, or true otherwise. /// </summary> /// <param name="model">Model to generate .apsimx files for.</param> /// <param name="path"> /// Path which the files will be saved to. /// If null, the user will be prompted to choose a directory. /// </param> public bool GenerateApsimXFiles(IModel model, string path = null) { if (string.IsNullOrEmpty(path)) { IFileDialog fileChooser = new FileDialog() { Prompt = "Select a directory to save model files to.", Action = FileDialog.FileActionType.SelectFolder }; path = fileChooser.GetFile(); if (!string.IsNullOrEmpty(path)) { MainPresenter.ShowMessage("Generating simulation files: ", Simulation.MessageType.Information); var runner = new Runner(model); var errors = Models.Core.Run.GenerateApsimXFiles.Generate(runner, path, (int percent) => { MainPresenter.ShowProgress(percent, false); }); if (errors == null || errors.Count == 0) { MainPresenter.ShowMessage("Successfully generated .apsimx files under " + path + ".", Simulation.MessageType.Information); return(true); } else { MainPresenter.ShowError(errors); return(false); } } } return(true); }
/// <summary>Save all changes.</summary> /// <returns>True if file was saved.</returns> public bool Save() { try { // Need to hide the right hand panel because some views may not have saved // their contents until they get a 'Detach' call. this.HideRightHandPanel(); if (this.ApsimXFile.FileName == null) { this.SaveAs(); } if (this.ApsimXFile.FileName != null) { this.ApsimXFile.Write(this.ApsimXFile.FileName); MainPresenter.ShowMessage(string.Format("Successfully saved to {0}", StringUtilities.PangoString(ApsimXFile.FileName)), Simulation.MessageType.Information); return(true); } } catch (Exception err) { this.MainPresenter.ShowError(new Exception("Cannot save the file. Error: ", err)); } finally { this.ShowRightHandPanel(); } return(false); }
/// <summary>Save the current file under a different name.</summary> /// <returns>True if file was saved.</returns> public bool SaveAs() { string newFileName = MainPresenter.AskUserForSaveFileName("ApsimX files|*.apsimx", this.ApsimXFile.FileName); if (newFileName != null) { try { /*if (this.ApsimXFile.FileName != null) * Utility.Configuration.Settings.DelMruFile(this.ApsimXFile.FileName); */ this.ApsimXFile.Write(newFileName); MainPresenter.ChangeTabText(this.view, Path.GetFileNameWithoutExtension(newFileName), newFileName); Utility.Configuration.Settings.AddMruFile(newFileName); MainPresenter.UpdateMRUDisplay(); MainPresenter.ShowMessage(string.Format("Successfully saved to {0}", newFileName), Simulation.MessageType.Information); return(true); } catch (Exception err) { this.MainPresenter.ShowError(new Exception("Cannot save the file. Error: ", err)); } } return(false); }
/// <summary>User has renamed a node.</summary> /// <param name="sender">Sending object</param> /// <param name="e">Event node arguments</param> private void OnRename(object sender, NodeRenameArgs e) { e.CancelEdit = false; if (e.NewName != null) { if (this.IsValidName(e.NewName)) { Model model = Apsim.Get(this.ApsimXFile, e.NodePath) as Model; if (model != null && model.GetType().Name != "Simulations" && e.NewName != string.Empty) { this.HideRightHandPanel(); string parentModelPath = StringUtilities.ParentName(e.NodePath); RenameModelCommand cmd = new RenameModelCommand(model, e.NewName, view); CommandHistory.Add(cmd); this.ShowRightHandPanel(); e.CancelEdit = (model.Name != e.NewName); } } else { MainPresenter.ShowMessage("Use alpha numeric characters only!", Simulation.ErrorLevel.Error); e.CancelEdit = true; } } }
/// <summary>Show a view in the right hand panel.</summary> /// <param name="model">The model.</param> /// <param name="viewName">The view name.</param> /// <param name="presenterName">The presenter name.</param> public void ShowInRightHandPanel(object model, string viewName, string presenterName) { try { object newView = Assembly.GetExecutingAssembly().CreateInstance(viewName, false, BindingFlags.Default, null, new object[] { this.view }, null, null); this.currentRightHandPresenter = Assembly.GetExecutingAssembly().CreateInstance(presenterName) as IPresenter; if (newView != null && this.currentRightHandPresenter != null) { // Resolve links in presenter. ApsimXFile.Links.Resolve(currentRightHandPresenter); this.view.AddRightHandView(newView); this.currentRightHandPresenter.Attach(model, newView, this); } } catch (Exception err) { if (err is System.Reflection.TargetInvocationException) { err = (err as System.Reflection.TargetInvocationException).InnerException; } string message = err.Message; message += "\r\n" + err.StackTrace; MainPresenter.ShowMessage(message, Simulation.ErrorLevel.Error); } }
/// <summary> /// Write all errors thrown during the loading of the <code>.apsimx</code> file. /// </summary> private void WriteLoadErrors() { if (this.ApsimXFile.LoadErrors != null) { foreach (Exception err in this.ApsimXFile.LoadErrors) { string message = string.Empty; if (err is ApsimXException) { message = string.Format("[{0}]: {1}", (err as ApsimXException).model, err.Message); } else { if (!string.IsNullOrEmpty(err.Source) && err.Source != "mscorlib") { message = "[" + err.Source + "]: "; } message += string.Format("{0}", err.Message + "\r\n" + err.StackTrace); } if (err.InnerException != null) { message += "\r\n" + err.InnerException.Message; } MainPresenter.ShowMessage(message, Simulation.ErrorLevel.Error); } } }
/// <summary>Save all changes.</summary> /// <returns>True if file was saved.</returns> public bool Save() { // Need to hide the right hand panel because some views may not have saved // their contents until they get a 'Detach' call. try { HideRightHandPanel(); if (string.IsNullOrEmpty(ApsimXFile.FileName)) { SaveAs(); } if (!string.IsNullOrEmpty(ApsimXFile.FileName)) { WriteSimulation(ApsimXFile.FileName); MainPresenter.ShowMessage(string.Format("Successfully saved to {0}", StringUtilities.PangoString(ApsimXFile.FileName)), Simulation.MessageType.Information); return(true); } } finally { ShowRightHandPanel(); } return(false); }
/// <summary> /// Generates .apsimx files for each child model under a given model. /// Returns false if errors were encountered, or true otherwise. /// </summary> /// <param name="model">Model to generate .apsimx files for.</param> /// <param name="path"> /// Path which the files will be saved to. /// If null, the user will be prompted to choose a directory. /// </param> public async Task <bool> GenerateApsimXFiles(IModel model, string path = null) { if (string.IsNullOrEmpty(path)) { IFileDialog fileChooser = new FileDialog() { Prompt = "Select a directory to save model files to.", Action = FileDialog.FileActionType.SelectFolder }; path = fileChooser.GetFile(); } if (!string.IsNullOrEmpty(path)) { MainPresenter.ShowMessage("Generating simulation files: ", Simulation.MessageType.Information); try { var runner = new Runner(model); await Task.Run(() => Models.Core.Run.GenerateApsimXFiles.Generate(runner, 1, path, p => MainPresenter.ShowProgress(p, false), true)); MainPresenter.ShowMessage("Successfully generated .apsimx files under " + path + ".", Simulation.MessageType.Information); return(true); } catch (Exception err) { MainPresenter.ShowError(err); return(false); } } return(true); }
/// <summary> /// Called by TabbedExplorerPresenter to do a save. Return true if all ok. /// </summary> /// <returns>True if saved</returns> public bool SaveIfChanged() { bool result = true; try { if (this.ApsimXFile != null && this.ApsimXFile.FileName != null) { QuestionResponseEnum choice = QuestionResponseEnum.No; if (!File.Exists(this.ApsimXFile.FileName)) { choice = MainPresenter.AskQuestion("The original file '" + this.ApsimXFile.FileName + "' no longer exists.\n \nClick \"Yes\" to save to this location or \"No\" to discard your work."); } else { // need to test is ApsimXFile has changed and only prompt when changes have occured. // serialise ApsimXFile to buffer StringWriter o = new StringWriter(); this.ApsimXFile.Write(o); string newSim = o.ToString(); StreamReader simStream = new StreamReader(this.ApsimXFile.FileName); string origSim = simStream.ReadToEnd(); // read original file to buffer2 simStream.Close(); if (string.Compare(newSim, origSim) != 0) { choice = MainPresenter.AskQuestion("Do you want to save changes in file " + this.ApsimXFile.FileName + " ?"); } } if (choice == QuestionResponseEnum.Cancel) { // cancel result = false; } else if (choice == QuestionResponseEnum.Yes) { // save // Need to hide the right hand panel because some views may not have saved // their contents until they get a 'Detach' call. this.HideRightHandPanel(); this.WriteSimulation(); result = true; } } } catch (Exception err) { MainPresenter.ShowMessage("Cannot save the file. Error: " + err.Message, Simulation.ErrorLevel.Error); result = false; } return(result); }
/// <summary> /// User has clicked download. /// </summary> /// <param name="sender">Event sender.</param> /// <param name="e">Event arguments.</param> private async void OnDownloadClicked(object sender, EventArgs e) { // Ask user for download path. string path = ViewBase.AskUserForFileName("Choose a download folder", Utility.FileDialog.FileActionType.SelectFolder, "", ApsimNG.Cloud.Azure.AzureSettings.Default.OutputDir); if (!string.IsNullOrEmpty(path)) { ApsimNG.Cloud.Azure.AzureSettings.Default.OutputDir = path; ApsimNG.Cloud.Azure.AzureSettings.Default.Save(); presenter.ShowWaitCursor(true); try { foreach (int listViewIndex in jobListView.SelectedIndicies) { var jobListIndex = ConvertListViewIndexToJobIndex(listViewIndex); DownloadOptions options = new DownloadOptions() { Name = jobList[jobListIndex].DisplayName, Path = ApsimNG.Cloud.Azure.AzureSettings.Default.OutputDir, JobID = Guid.Parse(jobList[jobListIndex].Id) }; await cloudInterface.DownloadResultsAsync(options, cancelToken.Token, p => { }); if (cancelToken.IsCancellationRequested) { return; } } presenter.ShowMessage($"Results were successfully downloaded to {ApsimNG.Cloud.Azure.AzureSettings.Default.OutputDir}", Simulation.MessageType.Information); } catch (Exception err) { presenter.ShowError(err); } finally { presenter.ShowWaitCursor(false); } } }
/// <summary>Hide the right hand panel.</summary> public void HideRightHandPanel() { if (this.currentRightHandPresenter != null) { try { this.currentRightHandPresenter.Detach(); this.currentRightHandPresenter = null; } catch (Exception err) { MainPresenter.ShowMessage(err.Message, Simulation.ErrorLevel.Error); } } this.view.AddRightHandView(null); }
/// <summary>A node has been dropped.</summary> /// <param name="sender">Sending object</param> /// <param name="e">Drop arguments</param> private void OnDrop(object sender, DropArgs e) { try { string toParentPath = e.NodePath; Model toParent = this.ApsimXFile.FindByPath(toParentPath)?.Value as Model; DragObject dragObject = e.DragObject as DragObject; if (dragObject != null && toParent != null) { string modelString = dragObject.ModelString; string fromParentPath = StringUtilities.ParentName(dragObject.NodePath); ICommand cmd = null; if (e.Moved) { if (fromParentPath != toParentPath) { Model fromModel = this.ApsimXFile.FindByPath(dragObject.NodePath)?.Value as Model; if (fromModel != null) { cmd = new MoveModelCommand(fromModel, toParent, GetNodeDescription); CommandHistory.Add(cmd); } } } else if (e.Copied) { var command = new AddModelCommand(toParent, modelString, GetNodeDescription); CommandHistory.Add(command, true); } else if (e.Linked) { // tbi MainPresenter.ShowMessage("Linked models TBI", Simulation.MessageType.Information); } view.Tree.ExpandChildren(toParent.FullPath, false); } } catch (Exception err) { MainPresenter.ShowError(err); } }
/// <summary>Show a view in the right hand panel.</summary> /// <param name="model">The model.</param> /// <param name="viewName">The view name.</param> /// <param name="presenterName">The presenter name.</param> public void ShowInRightHandPanel(object model, string viewName, string presenterName) { try { object newView = Assembly.GetExecutingAssembly().CreateInstance(viewName); this.currentRightHandPresenter = Assembly.GetExecutingAssembly().CreateInstance(presenterName) as IPresenter; if (newView != null && this.currentRightHandPresenter != null) { this.view.AddRightHandView(newView); this.currentRightHandPresenter.Attach(model, newView, this); } } catch (Exception err) { string message = err.Message; message += "\r\n" + err.StackTrace; MainPresenter.ShowMessage(message, DataStore.ErrorLevel.Error); } }
/// <summary> /// Called when the user wants to download results of a job. /// </summary> /// <param name="sender">Sender object.</param> /// <param name="args">Event arguments.</param> /// <returns></returns> private async Task OnDownloadJobs(object sender, EventArgs args) { DownloadOptions options = new DownloadOptions(); options.DownloadDebugFiles = view.DownloadDebugFiles; options.ExportToCsv = view.ExportCsv; options.ExtractResults = view.ExtractResults; string basePath = view.DownloadPath; view.DownloadProgress = 0; view.ShowDownloadProgressBar(); try { foreach (string id in view.GetSelectedJobIDs()) { JobDetails job = jobList.Find(j => j.Id == id); options.Path = Path.Combine(basePath, job.DisplayName + "_results"); options.JobID = Guid.Parse(id); await cloudInterface.DownloadResultsAsync(options, cancelToken.Token, p => view.DownloadProgress = p); if (cancelToken.IsCancellationRequested) { return; } } presenter.ShowMessage($"Results were successfully downloaded to {options.Path}", Simulation.MessageType.Information); } finally { view.HideDownloadProgressBar(); view.DownloadProgress = 0; } }
/// <summary> /// Pastes the contents of the clipboard. /// </summary> /// <param name="xml">The XML document text</param> /// <param name="parentPath">Path to the parent</param> public void Add(string xml, string parentPath) { try { XmlDocument document = new XmlDocument(); try { document.LoadXml(xml); } catch (XmlException) { MainPresenter.ShowMessage("Invalid XML. Are you sure you're trying to paste an APSIM model?", Simulation.ErrorLevel.Error); } object newModel = XmlUtilities.Deserialise(document.DocumentElement, this.ApsimXFile.GetType().Assembly); // See if the presenter is happy with this model being added. Model parentModel = Apsim.Get(this.ApsimXFile, parentPath) as Model; AllowDropArgs allowDropArgs = new AllowDropArgs(); allowDropArgs.NodePath = parentPath; allowDropArgs.DragObject = new DragObject() { NodePath = null, ModelType = newModel.GetType(), Xml = this.GetClipboardText() }; this.OnAllowDrop(null, allowDropArgs); // If it is happy then issue an AddModelCommand. if (allowDropArgs.Allow) { // If the model xml is a soil object then try and convert from old // APSIM format to new. if (document.DocumentElement.Name == "Soil" && XmlUtilities.Attribute(document.DocumentElement, "Name") != string.Empty) { XmlDocument newDoc = new XmlDocument(); newDoc.AppendChild(newDoc.CreateElement("D")); APSIMImporter importer = new APSIMImporter(); importer.ImportSoil(document.DocumentElement, newDoc.DocumentElement, newDoc.DocumentElement); XmlNode soilNode = XmlUtilities.FindByType(newDoc.DocumentElement, "Soil"); if (soilNode != null && XmlUtilities.FindByType(soilNode, "Sample") == null && XmlUtilities.FindByType(soilNode, "InitialWater") == null) { // Add in an initial water and initial conditions models. XmlNode initialWater = soilNode.AppendChild(soilNode.OwnerDocument.CreateElement("InitialWater")); XmlUtilities.SetValue(initialWater, "Name", "Initial water"); XmlUtilities.SetValue(initialWater, "PercentMethod", "FilledFromTop"); XmlUtilities.SetValue(initialWater, "FractionFull", "1"); XmlUtilities.SetValue(initialWater, "DepthWetSoil", "NaN"); XmlNode initialConditions = soilNode.AppendChild(soilNode.OwnerDocument.CreateElement("Sample")); XmlUtilities.SetValue(initialConditions, "Name", "Initial conditions"); XmlUtilities.SetValue(initialConditions, "Thickness/double", "1800"); XmlUtilities.SetValue(initialConditions, "NO3/double", "10"); XmlUtilities.SetValue(initialConditions, "NH4/double", "1"); XmlUtilities.SetValue(initialConditions, "NO3Units", "kgha"); XmlUtilities.SetValue(initialConditions, "NH4Units", "kgha"); XmlUtilities.SetValue(initialConditions, "SWUnits", "Volumetric"); } document.LoadXml(newDoc.DocumentElement.InnerXml); } IModel child = XmlUtilities.Deserialise(document.DocumentElement, this.ApsimXFile.GetType().Assembly) as IModel; AddModelCommand command = new AddModelCommand(parentModel, document.DocumentElement, this.GetNodeDescription(child), this.view); this.CommandHistory.Add(command, true); } } catch (Exception exception) { this.MainPresenter.ShowMessage(exception.Message, Simulation.ErrorLevel.Error); } }
/// <summary> /// Generates .apsimx files for each child model under a given model. /// Returns false if errors were encountered, or true otherwise. /// </summary> /// <param name="model">Model to generate .apsimx files for.</param> /// <param name="path"> /// Path which the files will be saved to. /// If null, the user will be prompted to choose a directory. /// </param> public bool GenerateApsimXFiles(IModel model, string path = null) { List <IModel> children; if (model is ISimulationGenerator) { children = new List <IModel> { model }; } else { children = Apsim.ChildrenRecursively(model, typeof(ISimulationGenerator)); } if (string.IsNullOrEmpty(path)) { IFileDialog fileChooser = new FileDialog() { Prompt = "Select a directory to save model files to.", Action = FileDialog.FileActionType.SelectFolder }; path = fileChooser.GetFile(); if (string.IsNullOrEmpty(path)) { return(false); } } if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } List <Exception> errors = new List <Exception>(); int i = 0; foreach (IModel sim in children) { MainPresenter.ShowMessage("Generating simulation files: ", Simulation.MessageType.Information); MainPresenter.ShowProgress(100 * i / children.Count, false); while (GLib.MainContext.Iteration()) { ; } try { (sim as ISimulationGenerator).GenerateApsimXFile(path); } catch (Exception err) { errors.Add(err); } i++; } if (errors.Count < 1) { MainPresenter.ShowMessage("Successfully generated .apsimx files under " + path + ".", Simulation.MessageType.Information); return(true); } else { MainPresenter.ShowError(errors); return(false); } }