/// <summary> /// Write all errors thrown during the loading of the <code>.apsimx</code> file. /// </summary> private void WriteLoadErrors() { if (this.ApsimXFile.LoadErrors != null) { MainPresenter.ShowError(ApsimXFile.LoadErrors); } }
/// <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> /// 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>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 TargetInvocationException) { err = (err as TargetInvocationException).InnerException; } string message = err.Message; message += "\r\n" + err.StackTrace; MainPresenter.ShowError(err); } }
/// <summary>Show a view in the right hand panel.</summary> /// <param name="model">The model.</param> /// <param name="newView">The view.</param> /// <param name="presenter">The presenter.</param> public void ShowInRightHandPanel(object model, ViewBase newView, IPresenter presenter) { try { this.currentRightHandPresenter = presenter; if (newView != null && this.currentRightHandPresenter != null) { // Resolve links in presenter. ApsimXFile.Links.Resolve(currentRightHandPresenter); this.view.AddRightHandView(newView); this.currentRightHandPresenter.Attach(model, newView, this); this.CurrentRightHandView = newView as ViewBase; } } catch (Exception err) { if (err is TargetInvocationException) { err = (err as TargetInvocationException).InnerException; } string message = err.Message; message += "\r\n" + err.StackTrace; MainPresenter.ShowError(err); } }
/// <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) { try { 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(); RenameModelCommand cmd = new RenameModelCommand(model, e.NewName, this.view); CommandHistory.Add(cmd); this.ShowRightHandPanel(); e.CancelEdit = model.Name != e.NewName; } } else { MainPresenter.ShowError("Use alpha numeric characters only!"); e.CancelEdit = true; } } } catch (Exception err) { MainPresenter.ShowError(err); } }
/// <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 hide the right hand panel because some views may not save // their contents until they get a 'Detach' call. this.HideRightHandPanel(); // 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 this.ShowRightHandPanel(); result = false; } else if (choice == QuestionResponseEnum.Yes) { // save this.WriteSimulation(); result = true; } } } catch (Exception err) { MainPresenter.ShowError(new Exception("Cannot save the file. Error: ", err)); this.ShowRightHandPanel(); result = false; } return(result); }
/// <summary>Moves the specified model down.</summary> /// <param name="model">The model to move.</param> public void MoveDown(IModel model) { try { MoveModelUpDownCommand command = new MoveModelUpDownCommand(model, false, this.view); CommandHistory.Add(command, true); } catch (Exception err) { MainPresenter.ShowError(err); } }
/// <summary>Deletes the specified model.</summary> /// <param name="model">The model to delete.</param> public void Delete(IModel model) { try { DeleteModelCommand command = new DeleteModelCommand(model, this.GetNodeDescription(model), this.view); CommandHistory.Add(command, true); } catch (Exception err) { MainPresenter.ShowError(err); } }
public void OnSaveClick(object sender, EventArgs e) { try { ExplorerPresenter explorer = presenter.GetCurrentExplorerPresenter(); if (explorer != null) { explorer.Save(); } } catch (Exception err) { presenter.ShowError(err); } }
/// <summary>A node has been selected (whether by user or undo/redo)</summary> /// <param name="sender">Sending object</param> /// <param name="e">Node arguments</param> private void OnNodeSelected(object sender, NodeSelectedArgs e) { try { this.HideRightHandPanel(); this.ShowRightHandPanel(); } catch (Exception err) { MainPresenter.ShowError(err); } // If an exception is thrown while loding the view, this // shouldn't interfere with the context menu. this.PopulateContextMenu(e.NewNodePath); }
/// <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.ShowError(err); } } 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>User has attempted to move the current node down.</summary> /// <param name="sender">The sender</param> /// <param name="e">The args</param> private void OnMoveDown(object sender, EventArgs e) { try { Model model = Apsim.Get(this.ApsimXFile, this.view.Tree.SelectedNode) as Model; if (model != null && model.Parent != null) { IModel lastModel = model.Parent.Children[model.Parent.Children.Count - 1]; if (model != lastModel) { CommandHistory.Add(new MoveModelUpDownCommand(model, false, this.view)); } } } catch (Exception err) { MainPresenter.ShowError(err); } }
/// <summary>User has attempted to move the current node up.</summary> /// <param name="sender">Sender object</param> /// <param name="e">Event arguments</param> private void OnMoveUp(object sender, EventArgs e) { try { Model model = Apsim.Get(ApsimXFile, view.Tree.SelectedNode) as Model; if (model != null && model.Parent != null) { IModel firstModel = model.Parent.Children[0]; if (model != firstModel) { CommandHistory.Add(new MoveModelUpDownCommand(model, true, view)); } } } catch (Exception err) { MainPresenter.ShowError(err); } }
/// <summary>Display a view on the right hand panel in view.</summary> public void ShowRightHandPanel() { try { if (this.view.Tree.SelectedNode != string.Empty) { object model = Apsim.Get(this.ApsimXFile, this.view.Tree.SelectedNode); if (model != null) { ViewNameAttribute viewName = ReflectionUtilities.GetAttribute(model.GetType(), typeof(ViewNameAttribute), false) as ViewNameAttribute; PresenterNameAttribute presenterName = ReflectionUtilities.GetAttribute(model.GetType(), typeof(PresenterNameAttribute), false) as PresenterNameAttribute; DescriptionAttribute descriptionName = ReflectionUtilities.GetAttribute(model.GetType(), typeof(DescriptionAttribute), false) as DescriptionAttribute; if (descriptionName != null && model.GetType().Namespace.Contains("CLEM")) { viewName = new ViewNameAttribute("UserInterface.Views.ModelDetailsWrapperView"); presenterName = new PresenterNameAttribute("UserInterface.Presenters.ModelDetailsWrapperPresenter"); } if (viewName == null && presenterName == null) { viewName = new ViewNameAttribute("UserInterface.Views.HTMLView"); presenterName = new PresenterNameAttribute("UserInterface.Presenters.GenericPresenter"); } ShowDescriptionInRightHandPanel(descriptionName?.ToString()); if (viewName != null && presenterName != null) { ShowInRightHandPanel(model, viewName.ToString(), presenterName.ToString()); } } } } catch (Exception err) { MainPresenter.ShowError(err); } }
/// <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 (!string.IsNullOrEmpty(ApsimXFile?.FileName)) { QuestionResponseEnum choice = QuestionResponseEnum.No; if (!File.Exists(ApsimXFile.FileName)) { choice = MainPresenter.AskQuestion("The original file '" + StringUtilities.PangoString(this.ApsimXFile.FileName) + "' no longer exists.\n \nClick \"Yes\" to save to this location or \"No\" to discard your work."); } else if (FileHasPendingChanges()) { choice = MainPresenter.AskQuestion("Do you want to save changes in file " + StringUtilities.PangoString(this.ApsimXFile.FileName) + " ?"); } if (choice == QuestionResponseEnum.Cancel) { ShowRightHandPanel(); result = false; } else if (choice == QuestionResponseEnum.Yes) { WriteSimulation(ApsimXFile.FileName); result = true; } } } catch (Exception err) { MainPresenter.ShowError(new Exception("Cannot save the file. Error: ", err)); result = false; } return(result); }
/// <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 = Apsim.Get(this.ApsimXFile, toParentPath) 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.Copied) { var command = new AddModelCommand(toParentPath, modelString, this); CommandHistory.Add(command, true); } else if (e.Moved) { if (fromParentPath != toParentPath) { Model fromModel = Apsim.Get(this.ApsimXFile, dragObject.NodePath) as Model; if (fromModel != null) { cmd = new MoveModelCommand(fromModel, toParent, this.GetNodeDescription(fromModel), this); CommandHistory.Add(cmd); } } } } } catch (Exception err) { MainPresenter.ShowError(err); } }
/// <summary> /// Called from a background worker thread. Updates the list of cloud jobs /// by interrogating the cloud platform. /// </summary> /// <param name="sender">Sender object.</param> /// <param name="args">Event arguments.</param> private async void ListJobs(object sender, DoWorkEventArgs args) { try { while (!fetchJobs.CancellationPending) // fixme { // Update the list of jobs. This will take some time. view.JobLoadProgress = 0; view.ShowLoadingProgressBar(); var newJobs = await cloudInterface.ListJobsAsync(cancelToken.Token, p => view.JobLoadProgress = p); if (fetchJobs.CancellationPending) { return; } if (Different(newJobs, jobList)) { view.UpdateJobTable(newJobs); } jobList = newJobs; view.HideLoadingProgressBar(); // Refresh job list every 10 seconds Thread.Sleep(10000); } } catch (Exception err) { presenter.ShowError(err); } finally { view?.HideLoadingProgressBar(); } }
/// <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(); } catch (Exception err) { MainPresenter.ShowError(err); } if (string.IsNullOrEmpty(ApsimXFile.FileName)) { SaveAs(); } if (!string.IsNullOrEmpty(ApsimXFile.FileName)) { ApsimXFile.Write(ApsimXFile.FileName); MainPresenter.ShowMessage(string.Format("Successfully saved to {0}", StringUtilities.PangoString(ApsimXFile.FileName)), Simulation.MessageType.Information); return(true); } try { ShowRightHandPanel(); } catch (Exception err) { MainPresenter.ShowError(err); } return(false); }
/// <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 err) { MainPresenter.ShowError(new Exception("Invalid XML. Are you sure you're trying to paste an APSIM model?", err)); } 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 err) { this.MainPresenter.ShowError(err); } }
/// <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); } }