diff --git a/Changelog.md b/Changelog.md index 073d429da..b78da76a4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -24,6 +24,7 @@ Be aware that code written for 1.9 will not work out of the box because DotSpati - Possibility to drag layers out of their group into the parent group (in legend) (#1008) - Clear parameter to Select function to speed up drawing (#1024) - LayoutControl.InitialOpenFileDirectory property that allows to set the folder that is shown in the OpenFileDialog that is used to open an existing layout +- FeatureLayer.Snappable to indicate whether the layer can be used for snapping ### Changed - Switched to VS2015 and C#6 @@ -44,6 +45,8 @@ Be aware that code written for 1.9 will not work out of the box because DotSpati - Made Shapefile class abstract, because we already have FeatureSet for creating unspecified Shapefiles (#890) - Moved MapFrame extension methods to Group (#1008) - Drawing functions so selected features are drawn on top (#897) +- ShapeEditors AddFeature and MoveVertex functions, so they snap only to the layers that allow snapping +- ShapeEditors SnapSettingsDialog to allow the users to select the layers the editor functions may snap to ### Removed - Removed DotSpatial.Topology assembly (#633) diff --git a/Source/DotSpatial.Plugins.ShapeEditor/ButtonHandler.cs b/Source/DotSpatial.Plugins.ShapeEditor/ButtonHandler.cs index 0f061ab68..7fa5b2897 100644 --- a/Source/DotSpatial.Plugins.ShapeEditor/ButtonHandler.cs +++ b/Source/DotSpatial.Plugins.ShapeEditor/ButtonHandler.cs @@ -352,14 +352,33 @@ private void SetSnapLayers(SnappableMapFunction func) private void SnappingButtonClick(object sender, EventArgs e) { - SnapSettingsDialog dlg = new SnapSettingsDialog + using (SnapSettingsDialog dlg = new SnapSettingsDialog(_geoMap) { DoSnapping = _doSnapping - }; - dlg.ShowDialog(); - _doSnapping = dlg.DoSnapping; - if (_moveVertexFunction != null) _moveVertexFunction.DoSnapping = _doSnapping; // changed by jany_ (2016-02-24) update the snap settings of the functions without having to stop editing - if (_addShapeFunction != null) _addShapeFunction.DoSnapping = _doSnapping; + }) + { + if (dlg.ShowDialog() == DialogResult.OK) + { + _doSnapping = dlg.DoSnapping; + if (_moveVertexFunction != null) + { + _moveVertexFunction.DoSnapping = _doSnapping; // changed by jany_ (2016-02-24) update the snap settings of the functions without having to stop editing + if (_doSnapping) + { + SetSnapLayers(_moveVertexFunction); + } + } + + if (_addShapeFunction != null) + { + _addShapeFunction.DoSnapping = _doSnapping; + if (_doSnapping) + { + SetSnapLayers(_addShapeFunction); + } + } + } + } } private void UpdateAddShapeFunctionLayer() diff --git a/Source/DotSpatial.Plugins.ShapeEditor/DotSpatial.Plugins.ShapeEditor.csproj b/Source/DotSpatial.Plugins.ShapeEditor/DotSpatial.Plugins.ShapeEditor.csproj index 1077b14d9..04c5916f3 100644 --- a/Source/DotSpatial.Plugins.ShapeEditor/DotSpatial.Plugins.ShapeEditor.csproj +++ b/Source/DotSpatial.Plugins.ShapeEditor/DotSpatial.Plugins.ShapeEditor.csproj @@ -132,6 +132,7 @@ True ShapeEditorResources.resx + Code diff --git a/Source/DotSpatial.Plugins.ShapeEditor/SnapLayer.cs b/Source/DotSpatial.Plugins.ShapeEditor/SnapLayer.cs new file mode 100644 index 000000000..6de9eba9f --- /dev/null +++ b/Source/DotSpatial.Plugins.ShapeEditor/SnapLayer.cs @@ -0,0 +1,60 @@ +// Copyright (c) DotSpatial Team. All rights reserved. +// Licensed under the MIT license. See License.txt file in the project root for full license information. + +using DotSpatial.Symbology; + +namespace DotSpatial.Plugins.ShapeEditor +{ + /// + /// Class to control layers snappable property through the datagridview. + /// + public class SnapLayer + { + #region Fields + + /// + /// Layer, whose snappable property can be changed. + /// + private readonly IFeatureLayer _layer; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// Layer, for which the SnapLayer-object gets created. + public SnapLayer(IFeatureLayer pLayer) + { + _layer = pLayer; + } + + #endregion + + #region Properties + + /// + /// Gets the layer name so it can be shown in the DataGridView. + /// + public string LayerName => _layer.LegendText; + + /// + /// Gets or sets a value indicating whether snapping to the coordinates of the layers features is allowed. + /// + public bool Snappable + { + get + { + return _layer.Snappable; + } + + set + { + _layer.Snappable = value; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.Designer.cs b/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.Designer.cs index b7203794c..9113a4a06 100644 --- a/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.Designer.cs +++ b/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.Designer.cs @@ -31,49 +31,134 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.cbPerformSnap = new System.Windows.Forms.CheckBox(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); this.btnSave = new System.Windows.Forms.Button(); + this.dgvLayer = new System.Windows.Forms.DataGridView(); + this.cbPerformSnap = new System.Windows.Forms.CheckBox(); + this.label1 = new System.Windows.Forms.Label(); + this.dgvcSnappable = new System.Windows.Forms.DataGridViewCheckBoxColumn(); + this.dgvcLayerName = new System.Windows.Forms.DataGridViewTextBoxColumn(); + ((System.ComponentModel.ISupportInitialize)(this.dgvLayer)).BeginInit(); this.SuspendLayout(); // + // btnSave + // + this.btnSave.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnSave.DialogResult = System.Windows.Forms.DialogResult.OK; + this.btnSave.Location = new System.Drawing.Point(197, 509); + this.btnSave.Name = "btnSave"; + this.btnSave.Size = new System.Drawing.Size(75, 23); + this.btnSave.TabIndex = 3; + this.btnSave.Text = "Save"; + this.btnSave.UseVisualStyleBackColor = true; + // + // dgvLayer + // + this.dgvLayer.AllowUserToAddRows = false; + this.dgvLayer.AllowUserToDeleteRows = false; + this.dgvLayer.AllowUserToResizeColumns = false; + this.dgvLayer.AllowUserToResizeRows = false; + this.dgvLayer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.dgvLayer.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill; + this.dgvLayer.BackgroundColor = System.Drawing.Color.White; + dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle1.BackColor = System.Drawing.Color.White; + dataGridViewCellStyle1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText; + dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True; + this.dgvLayer.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1; + this.dgvLayer.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dgvLayer.ColumnHeadersVisible = false; + this.dgvLayer.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.dgvcSnappable, + this.dgvcLayerName}); + this.dgvLayer.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically; + this.dgvLayer.GridColor = System.Drawing.Color.White; + this.dgvLayer.Location = new System.Drawing.Point(8, 59); + this.dgvLayer.MultiSelect = false; + this.dgvLayer.Name = "dgvLayer"; + this.dgvLayer.ReadOnly = true; + this.dgvLayer.RowHeadersVisible = false; + dataGridViewCellStyle2.BackColor = System.Drawing.Color.White; + dataGridViewCellStyle2.SelectionBackColor = System.Drawing.Color.White; + dataGridViewCellStyle2.SelectionForeColor = System.Drawing.Color.Black; + this.dgvLayer.RowsDefaultCellStyle = dataGridViewCellStyle2; + this.dgvLayer.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; + this.dgvLayer.Size = new System.Drawing.Size(264, 437); + this.dgvLayer.TabIndex = 2; + this.dgvLayer.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.DgvLayerCellContentClick); + // // cbPerformSnap // this.cbPerformSnap.AutoSize = true; this.cbPerformSnap.Checked = true; this.cbPerformSnap.CheckState = System.Windows.Forms.CheckState.Checked; - this.cbPerformSnap.Location = new System.Drawing.Point(12, 12); + this.cbPerformSnap.Location = new System.Drawing.Point(8, 12); this.cbPerformSnap.Name = "cbPerformSnap"; this.cbPerformSnap.Size = new System.Drawing.Size(110, 17); this.cbPerformSnap.TabIndex = 0; this.cbPerformSnap.Text = "Perform Snapping"; this.cbPerformSnap.UseVisualStyleBackColor = true; // - // btnSave + // label1 // - this.btnSave.DialogResult = System.Windows.Forms.DialogResult.OK; - this.btnSave.Location = new System.Drawing.Point(197, 70); - this.btnSave.Name = "btnSave"; - this.btnSave.Size = new System.Drawing.Size(75, 23); - this.btnSave.TabIndex = 1; - this.btnSave.Text = "Save"; - this.btnSave.UseVisualStyleBackColor = true; + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(5, 41); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(139, 13); + this.label1.TabIndex = 1; + this.label1.Text = "Snap to the following layers:"; + // + // dgvcSnappable + // + this.dgvcSnappable.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader; + this.dgvcSnappable.DataPropertyName = "Snappable"; + this.dgvcSnappable.FalseValue = "0"; + this.dgvcSnappable.HeaderText = "Snappable"; + this.dgvcSnappable.Name = "dgvcSnappable"; + this.dgvcSnappable.ReadOnly = true; + this.dgvcSnappable.Resizable = System.Windows.Forms.DataGridViewTriState.False; + this.dgvcSnappable.ToolTipText = "Indicates whether the coordinates of the layers features can be snapped to."; + this.dgvcSnappable.TrueValue = "1"; + this.dgvcSnappable.Width = 5; + // + // dgvcLayerName // - // SnapSettings + this.dgvcLayerName.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; + this.dgvcLayerName.DataPropertyName = "LayerName"; + this.dgvcLayerName.HeaderText = "Layer"; + this.dgvcLayerName.Name = "dgvcLayerName"; + this.dgvcLayerName.ReadOnly = true; + // + // SnapSettingsDialog // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(284, 105); - this.Controls.Add(this.btnSave); + this.ClientSize = new System.Drawing.Size(284, 544); + this.Controls.Add(this.label1); this.Controls.Add(this.cbPerformSnap); - this.Name = "SnapSettings"; + this.Controls.Add(this.dgvLayer); + this.Controls.Add(this.btnSave); + this.Name = "SnapSettingsDialog"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.Text = "Snap Settings"; + ((System.ComponentModel.ISupportInitialize)(this.dgvLayer)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion - - private CheckBox cbPerformSnap; private Button btnSave; + internal DataGridView dgvLayer; + private CheckBox cbPerformSnap; + private Label label1; + private DataGridViewCheckBoxColumn dgvcSnappable; + private DataGridViewTextBoxColumn dgvcLayerName; } } \ No newline at end of file diff --git a/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.cs b/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.cs index bc2628628..c2df5b174 100644 --- a/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.cs +++ b/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.cs @@ -1,7 +1,9 @@ // Copyright (c) DotSpatial Team. All rights reserved. // Licensed under the MIT license. See License.txt file in the project root for full license information. +using System.Collections.Generic; using System.Windows.Forms; +using DotSpatial.Controls; namespace DotSpatial.Plugins.ShapeEditor { @@ -13,9 +15,19 @@ public partial class SnapSettingsDialog : Form /// /// Initializes a new instance of the class. /// - public SnapSettingsDialog() + /// The map that contains the layers. + public SnapSettingsDialog(IMap map) { InitializeComponent(); + List snaplist = new List(); + + foreach (var layer in map.GetFeatureLayers()) + { + snaplist.Add(new SnapLayer(layer)); + } + + dgvLayer.AutoGenerateColumns = false; + dgvLayer.DataSource = snaplist; } /// @@ -26,5 +38,21 @@ public bool DoSnapping get { return cbPerformSnap.Checked; } set { cbPerformSnap.Checked = value; } } + + /// + /// Sets the check mark of the selected cell. + /// + /// The sender of the event. + /// The event args. + private void DgvLayerCellContentClick(object sender, DataGridViewCellEventArgs e) + { + if (e.RowIndex < 0 || e.ColumnIndex < 0) return; + + if (dgvLayer.Columns[e.ColumnIndex].Name == dgvcSnappable.Name) + { + DataGridViewRow row = dgvLayer.Rows[e.RowIndex]; + row.Cells[e.ColumnIndex].Value = !(bool)row.Cells[e.ColumnIndex].Value; + } + } } } diff --git a/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.resx b/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.resx index 29dcb1b3a..eecfa7b86 100644 --- a/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.resx +++ b/Source/DotSpatial.Plugins.ShapeEditor/SnapSettingsDialog.resx @@ -117,4 +117,10 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True + + + True + \ No newline at end of file diff --git a/Source/DotSpatial.Plugins.ShapeEditor/SnappableMapFunction.cs b/Source/DotSpatial.Plugins.ShapeEditor/SnappableMapFunction.cs index eb1989494..604ad2470 100644 --- a/Source/DotSpatial.Plugins.ShapeEditor/SnappableMapFunction.cs +++ b/Source/DotSpatial.Plugins.ShapeEditor/SnappableMapFunction.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Drawing; +using System.Linq; using DotSpatial.Controls; using DotSpatial.Data; using DotSpatial.Symbology; @@ -97,7 +98,7 @@ protected bool ComputeSnappedLocation(GeoMouseArgs e, ref Coordinate snappedCoor Envelope env = pix.ToEnvelope(); - foreach (IFeatureLayer layer in SnapLayers) + foreach (IFeatureLayer layer in SnapLayers.Where(_ => _.Snappable && _.IsVisible)) { foreach (IFeature feat in layer.DataSet.Features) { diff --git a/Source/DotSpatial.Symbology/FeatureLayer.cs b/Source/DotSpatial.Symbology/FeatureLayer.cs index 3b7d734ae..c8dacb48c 100644 --- a/Source/DotSpatial.Symbology/FeatureLayer.cs +++ b/Source/DotSpatial.Symbology/FeatureLayer.cs @@ -425,6 +425,14 @@ public virtual bool ShowLabels } } + /// + /// Gets or sets a value indicating whether this layer can be used for snapping. + /// + [Category("Behavior")] + [Description("Gets or sets a value indicating whether this layer can be used for snapping.")] + [Serialize("Snappable")] + public bool Snappable { get; set; } + /// /// Gets or sets and interface for the shared symbol characteristics between point, line and polygon features /// @@ -1709,6 +1717,7 @@ private void Configure(IFeatureSet featureSet) { _categoryExtents = new Dictionary(); DrawingBounds = new Rectangle(-32000, -32000, 64000, 64000); + Snappable = true; DataSet = featureSet; LegendText = featureSet.Name; Name = featureSet.Name; diff --git a/Source/DotSpatial.Symbology/IFeatureLayer.cs b/Source/DotSpatial.Symbology/IFeatureLayer.cs index 112e0faf2..c3a9b73b8 100644 --- a/Source/DotSpatial.Symbology/IFeatureLayer.cs +++ b/Source/DotSpatial.Symbology/IFeatureLayer.cs @@ -90,6 +90,13 @@ public interface IFeatureLayer : ILayer [Description("Gets or sets whether labels should be drawn.")] bool ShowLabels { get; set; } + /// + /// Gets or sets a value indicating whether this layer can be used for snapping. + /// + [Category("Behavior")] + [Description("Gets or sets a value indicating whether this layer can be used for snapping.")] + bool Snappable { get; set; } + /// /// Gets or sets and interface for the shared symbol characteristics between point, line and polygon features ///