public void OpenTestFileInTab() { // Open a simple .apsimx file in the GUI. explorerPresenter = UITestUtilities.OpenResourceFileInTab(Assembly.GetExecutingAssembly(), "UnitTests.ApsimNG.Resources.SampleFiles.BasicSimulation.apsimx"); // Create a table model. model = new DualTableModel(); model.Name = "Table"; // Create a datatable and assign it to the model. DataTable table = new DataTable(); table.Columns.Add("test_col", typeof(string)); table.Rows.Add("test"); model.Tables = new List <DataTable>() { table, table.Copy() }; // Add the model to the .apsimx file. Structure.Add(model, explorerPresenter.ApsimXFile); explorerPresenter.Refresh(); // Select the table model in the GUI. explorerPresenter.SelectNode(model); GtkUtilities.WaitForGtkEvents(); }
public void AddResourceModelToReplacements() { ExplorerPresenter explorerPresenter = UITestUtilities.OpenBasicFileInGui(); GtkUtilities.WaitForGtkEvents(); // Add a replacements node. Replacements replacements = new Replacements(); Structure.Add(replacements, explorerPresenter.ApsimXFile); explorerPresenter.Refresh(); // Select the replacements node, then activate the 'add model' context menu item. explorerPresenter.SelectNode(replacements); explorerPresenter.ContextMenu.AddModel(explorerPresenter, EventArgs.Empty); GtkUtilities.WaitForGtkEvents(); TreeView addModelsTree = (TreeView)ReflectionUtilities.GetValueOfFieldOrProperty("tree", explorerPresenter.CurrentPresenter); // Now, we double click on the fertiliser node. This should add a fertiliser model. // For some reason, sending a double click event doesn't trigger the ActivateRow signal. // Therefore, we need to manually activate the row. //GtkUtilities.ClickOnTreeView(treeView, path, 0, EventType.TwoButtonPress, ModifierType.None, GtkUtilities.ButtonPressType.LeftClick); ActivateNode(addModelsTree, ".Models.PMF.Wheat"); Assert.AreEqual(1, replacements.Children.Count, "Replacements should now have 1 child after adding wheat, but it doesn't"); Assert.AreEqual(typeof(Models.PMF.Plant), replacements.Children[0].GetType()); // Wheat should have some children (read in from the resource file). IModel wheat = replacements.Children[0]; Assert.NotZero(wheat.Children.Count); // The children should all be visible. foreach (IModel child in wheat.Children) { Assert.False(child.IsHidden); } }
public void CreateGraphs() { Simulations sims = CreateTemplate(); sims.FileName = Path.ChangeExtension(Path.GetTempFileName(), ".apsimx"); DataStore storage = sims.FindInScope <DataStore>(); storage.FileName = Path.ChangeExtension(sims.FileName, ".db"); // Run the file to populate the datastore. Runner runner = new Runner(sims); List <Exception> errors = runner.Run(); if (errors != null && errors.Count > 0) { throw errors[0]; } // Open the .apsimx file in the GUI. sims.Write(sims.FileName); ExplorerPresenter explorer = UITestsMain.MasterPresenter.OpenApsimXFileInTab(sims.FileName, true); GtkUtilities.WaitForGtkEvents(); sims = explorer.ApsimXFile; // Create a graphs folder under the zone. IModel paddock = sims.FindInScope <Zone>(); Folder graphs = new Folder(); graphs.Name = "Graphs"; var command = new AddModelCommand(paddock, graphs); explorer.CommandHistory.Add(command, true); // Add an empty graph to the folder. Models.Graph graph = new Models.Graph(); graph.Name = "Graph"; command = new AddModelCommand(graphs, graph); explorer.CommandHistory.Add(command, true); // Add an empty series to the graph. Models.Series series = new Models.Series(); series.Name = "Series"; command = new AddModelCommand(graph, series); explorer.CommandHistory.Add(command, true); explorer.Refresh(); // click on the series node. explorer.SelectNode(series.FullPath); GtkUtilities.WaitForGtkEvents(); // Get a reference to the OxyPlot PlotView via reflection. SeriesView seriesView = explorer.CurrentRightHandView as SeriesView; GraphView view = seriesView?.GraphView as GraphView; Assert.NotNull(view); PlotView plot = ReflectionUtilities.GetValueOfFieldOrProperty("plot1", view) as PlotView; Assert.NotNull(plot); // Series has no table name or x/y series names yet, so there should // be nothing shown on the graph. Assert.AreEqual(0, plot.Model.Series.Count); // Now draw some data on the graph. seriesView.DataSource.SelectedValue = "Report"; seriesView.X.SelectedValue = "n"; seriesView.Y.SelectedValue = "n2"; seriesView.SeriesType.SelectedValue = "Scatter"; GtkUtilities.WaitForGtkEvents(); // There should now be one series showing. Assert.AreEqual(1, plot.Model.Series.Count); // It should be a line series. Assert.True(plot.Model.Series[0] is LineSeries, "Graph series type is set to scatter, but the series object is not a LineSeries."); // Series colour should not be white, and should not be the same as the background colour. LineSeries line = plot.Model.Series[0] as LineSeries; OxyPlot.OxyColor empty = OxyPlot.OxyColor.FromArgb(0, 0, 0, 0); OxyPlot.OxyColor white = OxyPlot.OxyColor.FromArgb(0, 255, 255, 255); Assert.AreNotEqual(empty, line.Color, "Graph line series default colour is white on white."); Assert.AreNotEqual(white, line.Color, "Graph line series default colour is white on white."); // Legend should be visible but empty by default. Assert.True(plot.Model.IsLegendVisible); // todo - ensure legend is empty // Next, we want to change the legend position and ensure that the legend actually moves. // Click on the 'show in legend' checkbox. seriesView.ShowInLegend.Checked = true; GtkUtilities.WaitForGtkEvents(); // Double click on the middle of the legend. Cairo.Rectangle legendRect = plot.Model.LegendArea.ToRect(true); double x = (legendRect.X + (legendRect.X + legendRect.Width)) / 2; double y = (legendRect.Y + (legendRect.Y + legendRect.Height)) / 2; GtkUtilities.DoubleClick(plot, x, y, wait: true); // Default legend position should be top-left. Assert.AreEqual(plot.Model.LegendPosition, OxyPlot.LegendPosition.TopLeft); // Now we want to change the legend position. First, get a reference to the legend view // via the legend presenter, via the graph presenter, via the series presenter, via the explorer presenter. Assert.True(explorer.CurrentPresenter is SeriesPresenter); SeriesPresenter seriesPresenter = explorer.CurrentPresenter as SeriesPresenter; LegendPresenter legendPresenter = seriesPresenter.GraphPresenter.CurrentPresenter as LegendPresenter; // todo: should we add something like a GetView() method to the IPresenter interface? // It might be a bit of work to set up but would save us having to use reflection LegendView legendView = ReflectionUtilities.GetValueOfFieldOrProperty("view", legendPresenter) as LegendView; // The legend options are inside a Gtk expander. Assert.IsTrue(legendView.MainWidget.Parent is Expander); Expander expander = legendView.MainWidget.Parent as Expander; // The expander should be expanded and the options visible. Assert.IsTrue(expander.Expanded); Assert.IsTrue(legendView.MainWidget.Visible); // The legend view contains a combo box with the legend position options (top-right, bottom-left, etc). // This should really be refactored to use a public IDropDownView, which is much more convenient to use. // First, get a reference to the combo box via reflection. ComboBox combo = ReflectionUtilities.GetValueOfFieldOrProperty("combobox1", legendView) as ComboBox; // fixme - we should support all valid OxyPlot legend position types. foreach (Models.Graph.LegendPositionType legendPosition in Enum.GetValues(typeof(Models.Graph.LegendPositionType))) { string name = legendPosition.ToString(); GtkUtilities.SelectComboBoxItem(combo, name, wait: true); OxyPlot.LegendPosition oxyPlotEquivalent = (OxyPlot.LegendPosition)Enum.Parse(typeof(OxyPlot.LegendPosition), name); Assert.AreEqual(plot.Model.LegendPosition, oxyPlotEquivalent); } // If we change the graph to a box plot then the several unused properties should be disabled. // These are x variable dropdown, x cumulative, x on top, marker size/type checkboxes. // First, make sure that these options are sensitive to input and can be changed. Assert.IsTrue(seriesView.X.IsSensitive); Assert.IsTrue(seriesView.XCumulative.IsSensitive); Assert.IsTrue(seriesView.XOnTop.IsSensitive); Assert.IsTrue(seriesView.MarkerSize.IsSensitive); Assert.IsTrue(seriesView.MarkerType.IsSensitive); // Now change series type to box plot. GtkUtilities.SelectComboBoxItem(seriesView.SeriesType, "Box", wait: true); Assert.AreEqual(SeriesType.Box, series.Type); // Ensure the box plot is not white in light theme. plot = ReflectionUtilities.GetValueOfFieldOrProperty("plot1", view) as PlotView; Assert.NotNull(plot); BoxPlotSeries boxPlot = plot.Model.Series.OfType <BoxPlotSeries>().FirstOrDefault(); Assert.NotNull(boxPlot); Assert.AreNotEqual(empty, boxPlot.Fill); Assert.AreNotEqual(white, boxPlot.Fill); Assert.AreNotEqual(empty, boxPlot.Stroke); Assert.AreNotEqual(white, boxPlot.Stroke); // The controls should no longer be sensitive. Assert.IsFalse(seriesView.XCumulative.IsSensitive); Assert.IsFalse(seriesView.XOnTop.IsSensitive); Assert.IsFalse(seriesView.MarkerSize.IsSensitive); Assert.IsFalse(seriesView.MarkerType.IsSensitive); // Change the series type back to scatter. GtkUtilities.SelectComboBoxItem(seriesView.SeriesType, "Scatter", wait: true); // The controls should be sensitive once more. Assert.IsTrue(seriesView.X.IsSensitive); Assert.IsTrue(seriesView.XCumulative.IsSensitive); Assert.IsTrue(seriesView.XOnTop.IsSensitive); Assert.IsTrue(seriesView.MarkerSize.IsSensitive); Assert.IsTrue(seriesView.MarkerType.IsSensitive); }
/// <summary> /// Handles presses of the "ok" button /// Attempts to retrieve the indicated soil description and put it in place of the original soil. /// Closes the dialog if successful /// </summary> /// <param name="sender">Sender of the event</param> /// <param name="e">Event arguments</param> private void BtnOk_Clicked(object sender, EventArgs e) { try { if (!CheckValue(entryLatitude) || !CheckValue(entryLatitude)) { return; } if (String.IsNullOrWhiteSpace(entryFilePath.Text)) { ShowMessage(MessageType.Warning, "You must provide a file name for saving the weather data", "No file path"); BtnBrowse_Clicked(this, null); return; } string newWeatherPath = null; WaitCursor = true; try { if (radioSiloDataDrill.Active) { newWeatherPath = GetDataDrill(); } else if (radioSiloPatchPoint.Active) { newWeatherPath = GetPatchPoint(); } else if (radioNASA.Active) { newWeatherPath = GetNasaChirps(); } } finally { WaitCursor = false; } if (string.IsNullOrWhiteSpace(newWeatherPath)) { ShowMessage(MessageType.Error, "Unable to obtain data for this site", "Error"); } else { if (dest is Weather) { // If there is an existing Weather model (and there usually will be), is it better to replace // the model, or modify the FullFileName of the original? IPresenter currentPresenter = explorerPresenter.CurrentPresenter; if (currentPresenter is MetDataPresenter) { (currentPresenter as MetDataPresenter).OnBrowse(newWeatherPath); } else { explorerPresenter.CommandHistory.Add(new UserInterface.Commands.ChangeProperty(dest, "FullFileName", newWeatherPath)); } } else if (dest is Simulation) { Weather newWeather = new Weather(); newWeather.FullFileName = newWeatherPath; var command = new AddModelCommand(replaceNode, newWeather); explorerPresenter.CommandHistory.Add(command, true); explorerPresenter.Refresh(); } dialog1.Destroy(); } } catch (Exception err) { ShowMessage(MessageType.Error, err.Message, "Error"); } }