/// <summary> /// A method to compare if two MenuItems are the same. /// </summary> /// <param name="otherItem">The other MenuItem to compare with.</param> /// <returns>Bool indicating if they are the same.</returns> public bool Equals(MenuItem otherItem) { if (this.Title == otherItem.Title && this.FilePath == otherItem.FilePath) { return true; } else { return false; } }
/// <summary> /// Update the currentLocation object in order to setup the /// time slider for the images of the selected location. /// </summary> /// <param name="newLocation">New location value for currentLocation.</param> /// <param name="childToSelect">Child image for the location that should be visible.</param> private void UpdateCurrentLocation(MenuItem newLocation, MenuItem childToSelect) { this.currentLocation = newLocation; this.TimeSliderMax = this.currentLocation.Items.Count; // Set the TimeSlider to show the newly added child on the map bool foundChild = false; for (int i = 0; i < newLocation.Items.Count; i++) { if (newLocation.Items[i].Title == childToSelect.Title) { this.TimeSliderValue = i + 1; foundChild = true; break; } } // Default value just in case. if (!foundChild) { this.TimeSliderValue = 1; } }
/// <summary> /// This method converts all of the information from the remove layers /// window and returns it as a list of menuitems. This is how the /// remove layers window returns the results of the users actions. /// </summary> /// <returns>List of MenuItems including the user's checkbox selections.</returns> public List<MenuItem> GetMenuItems() { List<MenuItem> locationsToKeep = new List<MenuItem>(); // Don't include the root, which is the "All" selection. List<RemoveLayersViewModel> locations = this.root.Children; foreach (RemoveLayersViewModel location in locations) { // Add the location to the list. MenuItem loc; if (location.IsChecked == true) { loc = new MenuItem(location.Name, location.FilePath, location.TreeCanopyFilePath, true); } else { loc = new MenuItem(location.Name, location.FilePath, location.TreeCanopyFilePath, false); } // Add each of the times for that location to that children of that location. foreach (RemoveLayersViewModel time in location.Children) { MenuItem t; if (time.IsChecked == true) { t = new MenuItem(time.Name, time.FilePath, time.TreeCanopyFilePath, true); } else { t = new MenuItem(time.Name, time.FilePath, time.TreeCanopyFilePath, false); } loc.Items.Add(t); } locationsToKeep.Add(loc); } return locationsToKeep; }
/// <summary> /// Update the currentLocation object in order to setup the /// time slider for the images of the selected location. /// </summary> /// <param name="newLocation">New location value for currentLocation.</param> private void UpdateCurrentLocation(MenuItem newLocation) { if (newLocation == null) { return; } this.currentLocation = newLocation; this.TimeSliderMax = this.currentLocation.Items.Count; this.TimeSliderValue = 1; }
/// <summary> /// "Remove Layers" button callback. /// This pops up a window which allows the user to select which layers they wish to remove. /// The TreeView of layers is updated accordingly. /// </summary> /// <param name="parameter">Layer to be removed</param> private void RemoveLayer(object parameter) { RemoveLayers win = new RemoveLayers(RemoveLayersViewModel.CreateViewModels(this.TreeViewItems)); win.ShowDialog(); List<MenuItem> itemsList = win.GetMenuItems(); // For each parent for (int i = itemsList.Count - 1; i >= 0; i--) { // Remove all selected children for (int j = itemsList[i].Items.Count - 1; j >= 0; j--) { if (itemsList[i].Items[j].Checked) { this.UnloadKML(itemsList[i].Items[j].FilePath); this.UnloadKML(itemsList[i].Items[j].TreeCanopyFilePath); itemsList[i].Items.Remove(itemsList[i].Items[j]); } } // Remove the parent if necessary if (itemsList[i].Checked || itemsList[i].Items.Count == 0) { // KML layers are loaded and unloaded at the child level // so we do not need an UnloadKML here. itemsList.Remove(itemsList[i]); } } this.TreeViewItems = new ObservableCollection<MenuItem>(itemsList); win.Close(); // Update the current location. // First, check to see if the current location still exists. bool locationStillExists = false; foreach (MenuItem location in this.treeViewItems) { if (this.currentLocation.Title == location.Title) { // The location still exists, so update it // in case any DateTimes were removed from it. this.UpdateCurrentLocation(location); locationStillExists = true; break; } } // Or, if the location does not exist, then default to the first one. if (!locationStillExists) { this.currentLocation = this.treeViewItems.FirstOrDefault(); } List<Dataset> layers = new List<Dataset>(); string json; this.CollectAllTreeItems(this.treeViewItems, layers); json = JsonConvert.SerializeObject(layers.ToArray()); if (layers.Count == 0) { json = string.Empty; } System.IO.File.WriteAllText("../../Layers.json", json); }
/// <summary> /// Initializes a new instance of the <see cref="MainViewModel" /> class. /// This is the constructor for the MainViewModel. /// When the view model initializes, it reads the map from the App.xaml resources. /// </summary> /// <param name="window">The window the mainviewmodel belongs to.</param> public MainViewModel(MainWindow window) { this.mainWindow = window; this.viewTreeAnalytics = false; this.Map = App.Current.Resources["IncidentMap"] as Map; this.TreeViewItems = new ObservableCollection<MenuItem>(); // Read JSON file to get all existing layers List<Dataset> layers; string json; using (StreamReader r = new StreamReader("../../Layers.json")) { json = r.ReadToEnd(); layers = JsonConvert.DeserializeObject<List<Dataset>>(json); } // Backup to manually set up layers in case Layers.json is empty if (layers != null) { // Create MenuItems for all locations List<MenuItem> locations = new List<MenuItem>(); foreach (Dataset ds in layers) { MenuItem currentLocationRootNode = null; foreach (MenuItem item in locations) { if (item.Title == ds.Location) { currentLocationRootNode = item; } } // If location has not been added already if (currentLocationRootNode == null) { // Construct new root level node MenuItem node = new MenuItem() { Title = ds.Location, FilePath = ds.FilePath, TreeCanopyFilePath = ds.TreeCanopyFilePath }; // Add first subnode to new root level node node.Items.Add(new MenuItem() { Title = ds.Time.ToString(), FilePath = ds.FilePath, TreeCanopyFilePath = ds.TreeCanopyFilePath }); locations.Add(node); } else { // If location has been added already // Add another subnode to exisiting root level node currentLocationRootNode.Items.Add(new MenuItem() { Title = ds.Time.ToString(), FilePath = ds.FilePath, TreeCanopyFilePath = ds.TreeCanopyFilePath }); } } // Add root level nodes to tree foreach (MenuItem item in locations) { this.TreeViewItems.Add(item); } this.UpdateCurrentLocation(locations.First()); foreach (MenuItem item in locations.First().Items) { this.LoadKml(item.FilePath, true, true); } } this.datasetList = new List<Dataset>(); this.AddLayerCommand = new DelegateCommand(this.AddLayer); this.RemoveLayerCommand = new DelegateCommand(this.RemoveLayer); }
/// <summary> /// This method is called when the user clicks on an item in /// the layers treeview in the popout right side menu. It /// updates the currently selected image on the map as the /// one that the user clicked on. /// </summary> /// <param name="newlySelectedItem">The new images selected by /// the user to show on the map.</param> /// <param name="updateLocation">Flag to determine if we should set this location as the current /// location active on the time bar.</param> public void UpdateSelectedItem(MenuItem newlySelectedItem, bool updateLocation = true) { List<MenuItem> treeViewItemList = this.TreeViewItems.ToList(); // Iterate through each location. foreach (MenuItem location in treeViewItemList) { bool activeLocation = false; // First, check to see if the user clicked a location if (location.Equals(newlySelectedItem)) { // Failed attempt at panning on click //Layer selectedLayer = this.Map.Layers[location.Items.First().FilePath]; //this.MapView.SetView(selectedLayer.FullExtent.GetCenter()); // Very Ghetto way to pan to the selected image. if (this.ViewTreeAnalytics) { this.UnloadKML(location.Items.First().TreeCanopyFilePath); this.LoadKml(location.Items.First().TreeCanopyFilePath, true, true); } else { this.UnloadKML(location.Items.First().FilePath); this.LoadKml(location.Items.First().FilePath, true, true); } // If so, then select its first child if (updateLocation) { this.UpdateCurrentLocation(location); } location.Items.First().Checked = true; location.Checked = true; activeLocation = true; this.NotifiyPropertyChanged("TreeViewItems"); } else { // Else, iterate through this location's children to see if // one of them was selected. foreach (MenuItem time in location.Items) { // If this child was the selected item, // then set it as the active image. if (time.Equals(newlySelectedItem)) { if (updateLocation) { this.UpdateCurrentLocation(location, time); } // Very Ghetto way to pan to the selected image. if (this.ViewTreeAnalytics) { this.UnloadKML(time.TreeCanopyFilePath); this.LoadKml(time.TreeCanopyFilePath, true, true); } else { this.UnloadKML(time.FilePath); this.LoadKml(time.FilePath, true, true); } time.Checked = true; location.Checked = true; activeLocation = true; this.NotifiyPropertyChanged("TreeViewItems"); } else { time.Checked = false; } } } // If this location, nor any of its children // were selected, then make sure it is not highlighted. if (!activeLocation) { location.Checked = false; } } }
/// <summary> /// "Add Layer" button callback /// Pops up a window that gets the user to input the necessary information /// for adding a new layer and then adds the layer. /// </summary> /// <param name="parameter">The window being passed.</param> public void AddLayer(object parameter) { // Generate list of location names ObservableCollection<string> locations = new ObservableCollection<string>(); foreach (MenuItem item in this.treeViewItems) { locations.Add(item.Title); } // Popup a window to get the layer information AddLayer addLayer = new AddLayer(locations); addLayer.Owner = (Window)parameter; // In the XAML we pass the window as the parameter addLayer.ShowDialog(); // Get the data from the AddLayer window Dataset newLayer = addLayer.DatasetToAdd; addLayer.Close(); // Read JSON file with existing layers List<Dataset> layers; string json; using (StreamReader r = new StreamReader("../../Layers.json")) { json = r.ReadToEnd(); layers = JsonConvert.DeserializeObject<List<Dataset>>(json); } // Save new layer to flat JSON file if (layers == null) { layers = new List<Dataset>(); } layers.Add(newLayer); json = JsonConvert.SerializeObject(layers.ToArray()); System.IO.File.WriteAllText("../../Layers.json", json); if (!string.IsNullOrEmpty(newLayer.FilePath)) { // TODO - somewhere around here execute the code to do the tree analysis on the new image // Presently, this will not require a change in the treeview, so the new image can go straight // to LoadKML() TreeLineDetection temp = new TreeLineDetection(); Task.Run(() => temp.ConvertFolder((new FileInfo(newLayer.FilePath)).DirectoryName, this.mainWindow)); // Save the new dataset this.datasetList.Add(newLayer); // See if the Location already exists bool locationExists = false; foreach (MenuItem location in this.TreeViewItems) { // If so, then add the new layer as a child of that Location if (location.Title == newLayer.Location) { MenuItem newChild = new MenuItem(newLayer.Time.ToString(), newLayer.FilePath, location.TreeCanopyFilePath); location.Items.Add(newChild); // Sort the children based on time location.Items = new ObservableCollection<MenuItem>(location.Items.OrderBy(time => time.Title).ToList()); this.UpdateCurrentLocation(location, newChild); locationExists = true; break; } } // If not, then we also need to add the Location to the treeview if (!locationExists) { // Add it to the TreeView on the UI MenuItem root = new MenuItem(newLayer.Location, newLayer.FilePath, newLayer.TreeCanopyFilePath); root.Items.Add(new MenuItem(newLayer.Time.ToString(), newLayer.FilePath, newLayer.TreeCanopyFilePath)); this.TreeViewItems.Add(root); this.UpdateCurrentLocation(root); } // Open the new layer this.LoadKml(newLayer.FilePath, newLayer.ZoomTo, false); } Debug.WriteLine("Location: " + newLayer.Location); Debug.WriteLine("Time: " + newLayer.Time); Debug.WriteLine("File Path: " + newLayer.FilePath); }