diff --git a/KMZViewer.csproj b/KMZViewer.csproj index 7105d6d..2741276 100644 --- a/KMZViewer.csproj +++ b/KMZViewer.csproj @@ -85,7 +85,7 @@ - Form + Component MultiPointRouteForm.cs diff --git a/MultiPointRouteForm.Designer.cs b/MultiPointRouteForm.Designer.cs index 4dab468..d532eeb 100644 --- a/MultiPointRouteForm.Designer.cs +++ b/MultiPointRouteForm.Designer.cs @@ -32,7 +32,7 @@ private void InitializeComponent() this.buttonOk = new System.Windows.Forms.Button(); this.buttonCancel = new System.Windows.Forms.Button(); this.label1 = new System.Windows.Forms.Label(); - this.pbox = new System.Windows.Forms.CheckedListBox(); + this.pbox = new KMZRebuilder.MCLB(); this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); this.checkAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.checkNoneToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -42,6 +42,10 @@ private void InitializeComponent() this.deleteUncheckedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); this.clearAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator(); + this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator(); + this.importRoutePointsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.exportRoutePointsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.label2 = new System.Windows.Forms.Label(); this.contextMenuStrip1.SuspendLayout(); this.SuspendLayout(); @@ -71,9 +75,9 @@ private void InitializeComponent() this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(9, 7); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(324, 13); + this.label1.Size = new System.Drawing.Size(342, 13); this.label1.TabIndex = 2; - this.label1.Text = "Select points and order (Use Alt+Up/Ctrl+Down or Mouse to move):"; + this.label1.Text = "Select points and order (Use Alt+Up/Ctrl+Down or Alt+Mouse to move):"; // // pbox // @@ -98,62 +102,91 @@ private void InitializeComponent() this.deleteCheckedToolStripMenuItem, this.deleteUncheckedToolStripMenuItem, this.toolStripMenuItem2, - this.clearAllToolStripMenuItem}); + this.clearAllToolStripMenuItem, + this.toolStripMenuItem3, + this.toolStripMenuItem4, + this.importRoutePointsToolStripMenuItem, + this.exportRoutePointsToolStripMenuItem}); this.contextMenuStrip1.Name = "contextMenuStrip1"; - this.contextMenuStrip1.Size = new System.Drawing.Size(172, 148); + this.contextMenuStrip1.Size = new System.Drawing.Size(197, 226); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); // // checkAllToolStripMenuItem // this.checkAllToolStripMenuItem.Name = "checkAllToolStripMenuItem"; - this.checkAllToolStripMenuItem.Size = new System.Drawing.Size(171, 22); + this.checkAllToolStripMenuItem.Size = new System.Drawing.Size(196, 22); this.checkAllToolStripMenuItem.Text = "Check All"; this.checkAllToolStripMenuItem.Click += new System.EventHandler(this.checkAllToolStripMenuItem_Click); // // checkNoneToolStripMenuItem // this.checkNoneToolStripMenuItem.Name = "checkNoneToolStripMenuItem"; - this.checkNoneToolStripMenuItem.Size = new System.Drawing.Size(171, 22); + this.checkNoneToolStripMenuItem.Size = new System.Drawing.Size(196, 22); this.checkNoneToolStripMenuItem.Text = "Check None"; this.checkNoneToolStripMenuItem.Click += new System.EventHandler(this.checkNoneToolStripMenuItem_Click); // // inverseCheckedToolStripMenuItem // this.inverseCheckedToolStripMenuItem.Name = "inverseCheckedToolStripMenuItem"; - this.inverseCheckedToolStripMenuItem.Size = new System.Drawing.Size(171, 22); + this.inverseCheckedToolStripMenuItem.Size = new System.Drawing.Size(196, 22); this.inverseCheckedToolStripMenuItem.Text = "Inverse Checking"; this.inverseCheckedToolStripMenuItem.Click += new System.EventHandler(this.inverseCheckedToolStripMenuItem_Click); // // toolStripMenuItem1 // this.toolStripMenuItem1.Name = "toolStripMenuItem1"; - this.toolStripMenuItem1.Size = new System.Drawing.Size(168, 6); + this.toolStripMenuItem1.Size = new System.Drawing.Size(193, 6); // // deleteCheckedToolStripMenuItem // this.deleteCheckedToolStripMenuItem.Name = "deleteCheckedToolStripMenuItem"; - this.deleteCheckedToolStripMenuItem.Size = new System.Drawing.Size(171, 22); + this.deleteCheckedToolStripMenuItem.Size = new System.Drawing.Size(196, 22); this.deleteCheckedToolStripMenuItem.Text = "Delete Checked"; this.deleteCheckedToolStripMenuItem.Click += new System.EventHandler(this.deleteCheckedToolStripMenuItem_Click); // // deleteUncheckedToolStripMenuItem // this.deleteUncheckedToolStripMenuItem.Name = "deleteUncheckedToolStripMenuItem"; - this.deleteUncheckedToolStripMenuItem.Size = new System.Drawing.Size(171, 22); + this.deleteUncheckedToolStripMenuItem.Size = new System.Drawing.Size(196, 22); this.deleteUncheckedToolStripMenuItem.Text = "Delete Unchecked"; this.deleteUncheckedToolStripMenuItem.Click += new System.EventHandler(this.deleteUncheckedToolStripMenuItem_Click); // // toolStripMenuItem2 // this.toolStripMenuItem2.Name = "toolStripMenuItem2"; - this.toolStripMenuItem2.Size = new System.Drawing.Size(168, 6); + this.toolStripMenuItem2.Size = new System.Drawing.Size(193, 6); // // clearAllToolStripMenuItem // this.clearAllToolStripMenuItem.Name = "clearAllToolStripMenuItem"; - this.clearAllToolStripMenuItem.Size = new System.Drawing.Size(171, 22); + this.clearAllToolStripMenuItem.Size = new System.Drawing.Size(196, 22); this.clearAllToolStripMenuItem.Text = "Delete All"; this.clearAllToolStripMenuItem.Click += new System.EventHandler(this.clearAllToolStripMenuItem_Click); // + // toolStripMenuItem3 + // + this.toolStripMenuItem3.Name = "toolStripMenuItem3"; + this.toolStripMenuItem3.Size = new System.Drawing.Size(193, 6); + // + // toolStripMenuItem4 + // + this.toolStripMenuItem4.Name = "toolStripMenuItem4"; + this.toolStripMenuItem4.Size = new System.Drawing.Size(193, 6); + // + // importRoutePointsToolStripMenuItem + // + this.importRoutePointsToolStripMenuItem.Name = "importRoutePointsToolStripMenuItem"; + this.importRoutePointsToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.importRoutePointsToolStripMenuItem.Text = "Import Route Points ..."; + this.importRoutePointsToolStripMenuItem.Click += new System.EventHandler(this.importRoutePointsToolStripMenuItem_Click); + // + // exportRoutePointsToolStripMenuItem + // + this.exportRoutePointsToolStripMenuItem.Name = "exportRoutePointsToolStripMenuItem"; + this.exportRoutePointsToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.exportRoutePointsToolStripMenuItem.Text = "Export Route Points ..."; + this.exportRoutePointsToolStripMenuItem.Click += new System.EventHandler(this.exportRoutePointsToolStripMenuItem_Click); + // // label2 // this.label2.AutoSize = true; @@ -189,7 +222,7 @@ private void InitializeComponent() #endregion private System.Windows.Forms.Label label1; - private System.Windows.Forms.CheckedListBox pbox; + private MCLB pbox; private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; private System.Windows.Forms.ToolStripMenuItem checkAllToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem checkNoneToolStripMenuItem; @@ -202,5 +235,9 @@ private void InitializeComponent() public System.Windows.Forms.Button buttonOk; public System.Windows.Forms.Button buttonCancel; private System.Windows.Forms.Label label2; + private System.Windows.Forms.ToolStripMenuItem importRoutePointsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem exportRoutePointsToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4; } } \ No newline at end of file diff --git a/MultiPointRouteForm.cs b/MultiPointRouteForm.cs index 1c4cb31..9bd2e20 100644 --- a/MultiPointRouteForm.cs +++ b/MultiPointRouteForm.cs @@ -1,10 +1,17 @@ using System; +using System.IO; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; +using System.Text.RegularExpressions; using System.Windows.Forms; +using System.Xml; + +using ICSharpCode.SharpZipLib; +using ICSharpCode.SharpZipLib.Zip; +using ICSharpCode.SharpZipLib.Core; namespace KMZRebuilder { @@ -14,6 +21,7 @@ public partial class MultiPointRouteForm : Form object temp; int trackingItem; + bool trackingChecked; public MultiPointRouteForm() { @@ -112,27 +120,36 @@ private void pbox_MouseDown(object sender, MouseEventArgs e) { if (pbox.SelectedIndex < 0) return; - base.OnMouseDown(e); - pbox.Cursor = Cursors.Hand; - trackingItem = pbox.SelectedIndex; - if (trackingItem >= 0) - { temp = pbox.Items[pbox.SelectedIndex]; } + if ((Control.ModifierKeys & Keys.Alt) == Keys.Alt) + { + pbox.Cursor = Cursors.Hand; + trackingItem = pbox.SelectedIndex; + if (trackingItem >= 0) + { + temp = pbox.Items[pbox.SelectedIndex]; + trackingChecked = pbox.GetItemChecked(pbox.SelectedIndex); + pbox.MovingItem = temp; + }; + }; } private void pbox_MouseUp(object sender, MouseEventArgs e) { if (pbox.SelectedIndex < 0) return; - - base.OnMouseUp(e); - int tempInd = pbox.SelectedIndex; - if ((tempInd >= 0) && (trackingItem != tempInd)) - { - pbox.Items.RemoveAt(trackingItem); - pbox.Items.Insert(tempInd, temp); - pbox.SelectedIndex = tempInd; - pbox.SetItemChecked(tempInd, true); - }; - pbox.Cursor = Cursors.Default; + if (temp != null) + { + int tempInd = pbox.SelectedIndex; + if ((tempInd >= 0) && (trackingItem != tempInd)) + { + pbox.Items.RemoveAt(trackingItem); + pbox.Items.Insert(tempInd, temp); + pbox.SelectedIndex = tempInd; + pbox.SetItemChecked(tempInd, trackingChecked); + }; + pbox.Cursor = Cursors.Default; + temp = null; + pbox.MovingItem = null; + }; } private void checkAllToolStripMenuItem_Click(object sender, EventArgs e) @@ -171,6 +188,188 @@ private void clearAllToolStripMenuItem_Click(object sender, EventArgs e) { pbox.Items.Clear(); } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + exportRoutePointsToolStripMenuItem.Enabled = pbox.Items.Count > 0; + } + + private void exportRoutePointsToolStripMenuItem_Click(object sender, EventArgs e) + { + if (pbox.Items.Count == 0) return; + SaveFileDialog sfd = new SaveFileDialog(); + sfd.Title = "Export Route Points"; + sfd.Filter = "KMZ files (*.kml)|*.kml|KMZ files (*.kmz)|*.kmz"; + sfd.FileName = "ExportedRoutePoints.kml"; + string fName = null; + int filter = 0; + if (sfd.ShowDialog() == DialogResult.OK) { fName = sfd.FileName; filter = sfd.FilterIndex; }; + sfd.Dispose(); + if (String.IsNullOrEmpty(fName)) return; + if (filter == 1) SaveToKML(fName); + if (filter == 2) SaveToKMZ(fName); + } + + public void SaveToKML(string fName) + { + System.IO.FileStream fs = new System.IO.FileStream(fName, System.IO.FileMode.Create, System.IO.FileAccess.Write); + System.IO.StreamWriter sw = new System.IO.StreamWriter(fs, System.Text.Encoding.UTF8); + sw.WriteLine(""); + sw.WriteLine(""); + sw.WriteLine("Exported Route PointsExported Route Points"); + foreach(KeyValuePair np in this.Points) + { + sw.WriteLine(""); + sw.WriteLine(""); + sw.WriteLine("" + np.Value.X.ToString().Replace(",", ".") + "," + np.Value.Y.ToString().Replace(",", ".") + ",0.0"); + }; + sw.WriteLine(""); + sw.WriteLine(""); + sw.Close(); + fs.Close(); + } + + public void SaveToKMZ(string fName) + { + string inzip = fName + ".kml"; + SaveToKML(inzip); + + FileStream fsOut = File.Create(fName); + ZipOutputStream zipStream = new ZipOutputStream(fsOut); + zipStream.SetComment("Created by KMZRebuilder"); + zipStream.SetLevel(3); + // doc.kml + { + FileInfo fi = new FileInfo(inzip); + ZipEntry newEntry = new ZipEntry("doc.kml"); + newEntry.DateTime = fi.LastWriteTime; // Note the zip format stores 2 second granularity + newEntry.Size = fi.Length; + zipStream.PutNextEntry(newEntry); + + byte[] buffer = new byte[4096]; + using (FileStream streamReader = File.OpenRead(fi.FullName)) + StreamUtils.Copy(streamReader, zipStream, buffer); + zipStream.CloseEntry(); + }; + zipStream.IsStreamOwner = true; // Makes the Close also Close the underlying stream + zipStream.Close(); + + File.Delete(inzip); + } + + private void importRoutePointsToolStripMenuItem_Click(object sender, EventArgs e) + { + OpenFileDialog ofd = new OpenFileDialog(); + ofd.Title = "Import Route Points"; + ofd.Filter = "KML & KMZ files (*.kml,*.kmz)|*.kml;*.kmz"; + string fName = null; + if (ofd.ShowDialog() == DialogResult.OK) fName = ofd.FileName; + ofd.Dispose(); + if (String.IsNullOrEmpty(fName)) return; + LoadFromKMLZ(fName); + } + + public void LoadFromKMLZ(string fName) + { + FileStream fs = new FileStream(fName, FileMode.Open, FileAccess.Read); + StreamReader sr = new StreamReader(fs, System.Text.Encoding.UTF8); + string xml = sr.ReadToEnd(); + sr.Close(); + fs.Close(); + + xml = RemoveXMLNamespaces(xml); + XmlDocument kmlDoc = new XmlDocument(); + kmlDoc.LoadXml(xml); + XmlNodeList xnf = kmlDoc.SelectNodes("kml/Document/Folder/Placemark"); + foreach (XmlNode xp in xnf) + { + XmlNode xnn = xp.SelectNodes("Point/coordinates")[0]; + if (xp != null) + { + string[] llz = xnn.ChildNodes[0].Value.Replace("\r", "").Replace("\n", "").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + string name = "NoName"; + try { name = xnn.ParentNode.ParentNode.SelectSingleNode("name").ChildNodes[0].Value; } + catch { }; + PointF pf = new PointF((float)double.Parse(llz[0], System.Globalization.CultureInfo.InvariantCulture), (float)double.Parse(llz[1], System.Globalization.CultureInfo.InvariantCulture)); + pbox.Items.Add(new KeyValuePair(name, pf), true); + OnMapPoints.Add(pf); + }; + }; + } + + public static string RemoveXMLNamespaces(string xml) + { + string outerXml = xml; + { // " + string xmlnsPattern = "\\s+xmlns\\s*(:\\w)?\\s*=\\s*\\\"(?[^\\\"]*)\\\""; + MatchCollection matchCol = Regex.Matches(outerXml, xmlnsPattern); + foreach (Match match in matchCol) + outerXml = outerXml.Replace(match.ToString(), ""); + }; + {// ' + string xmlnsPattern = "\\s+xmlns\\s*(:\\w)?\\s*=\\s*\\\'(?[^\\\']*)\\\'"; + MatchCollection matchCol = Regex.Matches(outerXml, xmlnsPattern); + foreach (Match match in matchCol) + outerXml = outerXml.Replace(match.ToString(), ""); + }; + { + string xmlnsPattern = "]*?>"; + MatchCollection matchCol = Regex.Matches(outerXml, xmlnsPattern); + foreach (Match match in matchCol) + outerXml = outerXml.Replace(match.ToString(), ""); + }; + return outerXml; + } + } + + public class MCLB : CheckedListBox + { + public object MovingItem = null; + protected override void OnDrawItem(DrawItemEventArgs e) + { + Size checkSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, System.Windows.Forms.VisualStyles.CheckBoxState.MixedNormal); + int dx = (e.Bounds.Height - checkSize.Width) / 2; + + e.DrawBackground(); + + if (e.Index >= 0) + { + try + { + bool isChecked = GetItemChecked(e.Index); + bool isSelected = ((e.State & DrawItemState.Selected) == DrawItemState.Selected); + if (isChecked) + { + e.Graphics.DrawString("v", new Font(e.Font, FontStyle.Bold), isSelected ? SystemBrushes.HighlightText : SystemBrushes.WindowText, new PointF(dx + 1, e.Bounds.Top)); + } + else + { + if (isSelected) + e.Graphics.FillRectangle(Brushes.DarkSlateBlue, e.Bounds); + else + e.Graphics.FillRectangle(Brushes.Yellow, e.Bounds); + }; + + Pen myp = new Pen(new SolidBrush(Color.FromArgb(230, 230, 250))); + myp.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; + e.Graphics.DrawLine(myp, new Point(e.Bounds.Left, e.Bounds.Bottom - 1), new Point(e.Bounds.Right, e.Bounds.Bottom - 1)); + int offset = e.Bounds.Left + e.Font.Height + 2; + e.Graphics.DrawLine(myp, new Point(offset, e.Bounds.Top), new Point(offset, e.Bounds.Bottom - 1)); + offset += 5; + + string name = this.Items[e.Index].ToString(); + if ((MovingItem != null) && isSelected) + { + e.Graphics.FillRectangle(Brushes.Fuchsia, e.Bounds); + if (isChecked) e.Graphics.DrawString("v", new Font(e.Font, FontStyle.Bold), isSelected ? SystemBrushes.HighlightText : SystemBrushes.WindowText, new PointF(dx + 1, e.Bounds.Top)); + name = MovingItem.ToString(); + }; + e.Graphics.DrawString(name, e.Font, isSelected ? SystemBrushes.HighlightText : Brushes.Black, new Rectangle(offset, e.Bounds.Top, e.Bounds.Width - offset, e.Bounds.Height), StringFormat.GenericDefault); + } + catch { }; + }; + } + } } \ No newline at end of file diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index ef9440d..08818cd 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -37,5 +37,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion("22.1.14.111")] -[assembly: AssemblyFileVersion("22.1.14.111")] +[assembly: AssemblyVersion("22.1.18.113")] +[assembly: AssemblyFileVersion("22.1.18.113")] diff --git a/bin/Debug/KMZViewer.exe b/bin/Debug/KMZViewer.exe index 1afbf6d..a5310d5 100644 Binary files a/bin/Debug/KMZViewer.exe and b/bin/Debug/KMZViewer.exe differ