using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Drawing; using System.Linq; using System.Windows.Forms; using Core.Common.Base; using Core.Common.Base.Workflow; using Core.Common.Controls; using Core.Common.Controls.Swf.Table; using Core.Common.Gui; using Core.Common.Gui.Forms; using Core.Common.Utils; using Core.GIS.GeoAPI.Extensions.Feature; using Core.GIS.GeoAPI.Geometries; using Core.GIS.SharpMap.Api.Layers; using Core.GIS.SharpMap.Data.Providers; using Core.GIS.SharpMap.Layers; using Core.GIS.SharpMap.Map; using Core.GIS.SharpMap.UI.Forms; using Core.GIS.SharpMap.UI.Tools; using Core.GIS.SharpMap.UI.Tools.Decorations; using Core.Plugins.SharpMapGis.Gui.Forms; using Core.Plugins.SharpMapGis.Gui.Forms.MapLegendView; using Core.Plugins.SharpMapGis.Gui.NodePresenters; using PropertyInfo = Core.Common.Gui.PropertyInfo; namespace Core.Plugins.SharpMapGis.Gui { public class SharpMapGisGuiPlugin : GuiPlugin { private static IGui gui; private static MapLegendView mapLegendView; private static IGisGuiService gisGuiService; private IRibbonCommandHandler ribbonCommandHandler; public SharpMapGisGuiPlugin() { Instance = this; gisGuiService = new GisGuiService(this); } public override IRibbonCommandHandler RibbonCommandHandler { get { if (ribbonCommandHandler == null) { var ribbon = new Ribbon(); ribbonCommandHandler = ribbon; } return ribbonCommandHandler; } } public override IGui Gui { get { return gui; } set { gui = value; } } public static SharpMapGisGuiPlugin Instance { get; private set; } public IGisGuiService GisGuiService { get { return gisGuiService; } set { gisGuiService = value; } } public MapLegendView MapLegendView { get { return mapLegendView; } } /// /// Creates a object for /// a IEnumerable of TFeature that is present part of a TFeatureContainer /// /// /// Model - boundaries /// /// var viewInfo = CreateAttributeTableViewInfo]]>(m => m.Boundaries, () => Gui) /// /// /// Type of the sub features /// Type of the feature container /// Function for getting the IEnumerable of from /// Function for getting an public static ViewInfo, ILayer, VectorLayerAttributeTableView> CreateAttributeTableViewInfo(Func> getCollection, Func getGui) { return new ViewInfo, ILayer, VectorLayerAttributeTableView> { Description = "Attribute Table", GetViewName = (v, o) => o.Name, AdditionalDataCheck = o => { var container = getGui().Application.Project.Items.OfType().FirstOrDefault(fc => Equals(o, getCollection(fc))); return container != null; }, GetViewData = o => { var centralMap = getGui().DocumentViews.OfType() .FirstOrDefault(v => v.MapView.GetLayerForData(o) != null); return centralMap == null ? null : centralMap.MapView.GetLayerForData(o); }, CompositeViewType = typeof(ProjectItemMapView), GetCompositeViewData = o => getGui().Application.Project.Items.OfType().FirstOrDefault(fc => { if (fc is TFeatureContainer) { return Equals(o, getCollection((TFeatureContainer) fc)); } return false; }), AfterCreate = (v, o) => { var centralMap = getGui().DocumentViews.OfType() .FirstOrDefault(vi => vi.MapView.GetLayerForData(o) != null); if (centralMap == null) { return; } v.DeleteSelectedFeatures = () => centralMap.MapView.MapControl.DeleteTool.DeleteSelection(); v.OpenViewMethod = ob => getGui().CommandHandler.OpenView(ob); v.ZoomToFeature = feature => centralMap.MapView.EnsureVisible(feature); v.CanAddDeleteAttributes = false; } }; } public void InitializeMapLegend() { if ((mapLegendView == null) || (mapLegendView.IsDisposed)) { mapLegendView = new MapLegendView(gui) { OnOpenLayerAttributeTable = layer => { var mapView = GetFocusedMapView(); if (mapView == null) { return; } var layerData = mapView.GetDataForLayer != null ? mapView.GetDataForLayer(layer) : null; if (!Gui.DocumentViewsResolver.OpenViewForData(layerData, typeof(ILayerEditorView)) && layer is VectorLayer) { mapView.OpenLayerAttributeTable(layer, o => gui.CommandHandler.OpenView(o)); } }, Text = Properties.Resources.SharpMapGisPluginGui_InitializeMapLegend_Map_Contents }; } // TODO: subscribe to mapLegendView.TreeView.SelectionChanged! and update Gui.Selection if necessary if (gui.ToolWindowViews != null) { gui.ToolWindowViews.Add(mapLegendView, ViewLocation.Left | ViewLocation.Bottom); gui.ToolWindowViews.ActiveView = mapLegendView; } } public override void Activate() { InitializeMapLegend(); if (Gui != null && Gui.DocumentViews != null && Gui.DocumentViews.ActiveView != null) { DocumentViewsActiveViewChanged(Gui, null); } gui.SelectionChanged += GuiSelectionChanged; gui.DocumentViews.ActiveViewChanged += DocumentViewsActiveViewChanged; gui.DocumentViews.ChildViewChanged += DocumentViewsActiveViewChanged; gui.Application.ProjectClosing += ApplicationProjectClosing; if (gui.Application.ActivityRunner != null) { gui.Application.ActivityRunner.ActivityCompleted += ActivityRunnerOnActivityCompleted; } } public override void Dispose() { if (gui != null) { gui.SelectionChanged -= GuiSelectionChanged; var documentViews = gui.DocumentViews; if (documentViews != null) { documentViews.ChildViewChanged -= DocumentViewsActiveViewChanged; documentViews.ActiveViewChanged -= DocumentViewsActiveViewChanged; } var application = gui.Application; if (gui.Application != null) { application.ProjectClosing -= ApplicationProjectClosing; if (application.ActivityRunner != null) { application.ActivityRunner.ActivityCompleted -= ActivityRunnerOnActivityCompleted; } } } gui = null; Instance = null; mapLegendView = null; gisGuiService = null; } public override void OnViewRemoved(IView view) { UpdateMapLegendView(); var mapView = GetFocusedMapView(view); if (mapView == null) { return; } mapView.MapControl.SelectedFeaturesChanged -= MapControlSelectedFeaturesChanged; mapView.MapControl.MouseDoubleClick -= mapView_MouseDoubleClick; mapView.Map.MapRendered -= MapMapRendered; } public override IEnumerable GetPropertyInfos() { return SharpMapGisPropertyInfoProvider.GetPropertyInfos(); } public override IEnumerable GetViewInfoObjects() { yield return new ViewInfo { Description = "Map" }; yield return new ViewInfo { Description = "Attribute table", CompositeViewType = typeof(ProjectItemMapView), GetViewName = (v, o) => o.Name + " Attributes" }; yield return new ViewInfo { Description = "Table" }; yield return new ViewInfo { Description = "Map", AdditionalDataCheck = o => CanLayerProvidersCreateLayerFor(o), GetViewData = o => o, GetViewName = (v, o) => o.Name, OnActivateView = (v, o) => { var layerData = o; var layer = v.MapView.GetLayerForData(layerData); if (layer != null) { v.MapView.EnsureVisible(layer); if (MapLegendView != null) { MapLegendView.EnsureVisible(layer); } } }, AfterCreate = (v, o) => { var mapLayerProviders = Gui.Plugins.Select(p => p.MapLayerProvider).Where(p => p != null).ToList(); v.CreateLayerForData = (lo, ld) => MapLayerProviderHelper.CreateLayersRecursive(lo, null, mapLayerProviders, ld); v.RefreshLayersAction = (l, ld, po) => MapLayerProviderHelper.RefreshLayersRecursive(l, ld, mapLayerProviders, po); }, CloseForData = (v, o) => v.Data.Equals(o) // only close the view if it is the root object }; } public override ContextMenuStrip GetContextMenu(object sender, object data) { //custom treenodes for maplegend view if (sender is TreeNode) { var treeNode = (TreeNode)sender; if (treeNode.TreeView.Parent == mapLegendView) { return mapLegendView != null ? mapLegendView.GetContextMenu(data) : null; } } return null; } public override IEnumerable GetProjectTreeViewNodePresenters() { yield return new MapProjectTreeViewNodePresenter { GuiPlugin = this }; } public override bool CanDrop(object source, object target) { if (source is ILayer && target is Map) { return true; } if (source is IList && target is Map && ((IEnumerable) source).Cast().FirstOrDefault() is IGeometry) { return true; } return false; } public override void OnDragDrop(object source, object target) { var map = target as Map; if (map == null) { return; } if (source is ILayer) { map.Layers.Add((ILayer) source); } if (source is IList) { var items = (IList) source; if (items.Count > 0 && items[0] is IGeometry) { var provider = new FeatureCollection(); foreach (var item in items) { var geometry = (IGeometry) item; provider.Features.Add(geometry); } ILayer layer = new VectorLayer { DataSource = provider }; map.Layers.Add(layer); } if (items.Count > 0 && items[0] is IFeature) { var provider = new FeatureCollection { Features = items }; ILayer layer = new VectorLayer { DataSource = provider }; map.Layers.Add(layer); } } map.NotifyObservers(); } internal static MapView GetFocusedMapView(IView view = null) { return gui.GetFocusedMapView(view); } private void ApplicationProjectClosing(Project project) { if (gui == null) { return; } if (mapLegendView != null) { mapLegendView.Map = null; } } private static void GuiSelectionChanged(object sender, SelectedItemChangedEventArgs e) { // Send selection to all relevant views var selection = gui.Selection; if ((selection is IFeature) || (selection == null)) { // Try to select the feature on the map corresponding to the selected row in the data table foreach (var view in gui.DocumentViews.AllViews.OfType().Where(view => view.IsAllowSyncWithGuiSelection)) { view.MapControl.SelectedFeaturesChanged -= MapControlSelectedFeaturesChanged; view.MapControl.SelectTool.Select((IFeature) selection); view.MapControl.SelectedFeaturesChanged += MapControlSelectedFeaturesChanged; } } else if (selection is IEnumerable && ((IEnumerable) selection).OfType().Any()) { // If the selection was made from within the map control, also select it in the corresponding attribute table var selectedFeatures = ((IEnumerable) selection).OfType(); if (!selectedFeatures.Any()) { return; } foreach (var view in gui.DocumentViews.AllViews.OfType().Where(view => view.IsAllowSyncWithGuiSelection)) { view.MapControl.SelectedFeaturesChanged -= MapControlSelectedFeaturesChanged; view.MapControl.SelectTool.Select(selectedFeatures); view.MapControl.SelectedFeaturesChanged += MapControlSelectedFeaturesChanged; } } } private void DocumentViewsActiveViewChanged(object sender, EventArgs e) { UpdateMapLegendView(); var mapView = GetFocusedMapView(); if (mapView != null) { mapView.MapControl.MouseDoubleClick -= mapView_MouseDoubleClick; mapView.MapControl.MouseDoubleClick += mapView_MouseDoubleClick; mapView.MapControl.ToolActivated -= MapControlOnToolActivated; mapView.MapControl.ToolActivated += MapControlOnToolActivated; var openViewTool = mapView.MapControl.GetToolByType(); if (openViewTool != null && openViewTool.OpenView == null) { openViewTool.OpenView = feature => gui.DocumentViewsResolver.OpenViewForData(feature); openViewTool.CanOpenView = feature => gui.DocumentViewsResolver.CanOpenViewFor(feature); } if (mapView.IsAllowSyncWithGuiSelection) { mapView.MapControl.SelectedFeaturesChanged -= MapControlSelectedFeaturesChanged; mapView.MapControl.SelectedFeaturesChanged += MapControlSelectedFeaturesChanged; } mapView.Map.MapRendered -= MapMapRendered; mapView.Map.MapRendered += MapMapRendered; } } private static void MapControlOnToolActivated(object sender, EventArgs eventArgs) { RefreshRibbonItems(); } private void ActivityRunnerOnActivityCompleted(object sender, ActivityEventArgs e) { if (mapLegendView == null) { return; } // Force a refresh of the map legend view (tree view) mapLegendView.Data = null; UpdateMapLegendView(); } private static void UpdateMapLegendView() { if (mapLegendView == null) { return; } var mapView = GetFocusedMapView(); if (mapView != null) { if (!Equals(mapLegendView.Data, mapView.Data)) { // only update when data is changed, mapLegendView.Data = mapView.Data; } } else { mapLegendView.Data = null; } } private static void RefreshRibbonItems() { gui.MainWindow.ValidateItems(); } private static void MapMapRendered(Graphics g) { RefreshRibbonItems(); } // TODO: WTF?!? Use mapControl.SelectTool.SelectTool.SelectionChanged += ... // Reason why not to: AddTool and EditTool also have their own selection mechanism private static void MapControlSelectedFeaturesChanged(object sender, EventArgs e) { gui.SelectionChanged -= GuiSelectionChanged; var mapControl = (MapControl) sender; IList selectedFeatures = mapControl.SelectedFeatures.ToList(); if (selectedFeatures.Count != 0) { gui.Selection = selectedFeatures.Count == 1 ? (object) selectedFeatures[0] : selectedFeatures; } else { var selectedLayoutComponentTool = mapControl.Tools.OfType().FirstOrDefault(t => t.Selected); gui.Selection = selectedLayoutComponentTool; } gui.SelectionChanged += GuiSelectionChanged; } private static void mapView_MouseDoubleClick(object sender, MouseEventArgs e) { IEnumerable selectedFeatures = ((MapControl) sender).SelectedFeatures; if (selectedFeatures == null || !selectedFeatures.Any()) { return; } var data = selectedFeatures.First(); gui.CommandHandler.OpenView(data); } private bool CanLayerProvidersCreateLayerFor(object data) { if (Gui == null || Gui.Plugins == null) { return false; } return Gui.Plugins.Select(p => p.MapLayerProvider) .Where(p => p != null) .Any(p => p.CanCreateLayerFor(data, Gui.SelectedProjectItem)); } } }