#region Disclaimer / License // Copyright (C) 2011, Jackie Ng // http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie@gmail.com // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // #endregion using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; using OSGeo.MapGuide.ObjectModels.FeatureSource; using OSGeo.MapGuide.MaestroAPI.SchemaOverrides; using System.Xml; using OSGeo.MapGuide.MaestroAPI.Schema; using System.IO; using Maestro.Shared.UI; using OSGeo.MapGuide.MaestroAPI.Resource; using OSGeo.MapGuide.ObjectModels; using OSGeo.MapGuide.MaestroAPI; using System.Collections.Specialized; using Maestro.Editors.Common; using System.Globalization; namespace Maestro.Editors.FeatureSource.Providers.Gdal { [ToolboxItem(false)] internal partial class CompositeFileCtrl : EditorBase { internal CompositeFileCtrl() { InitializeComponent(); } private IFeatureSource _fs; private GdalConfigurationDocument _conf; private IEditorService _service; public override void Bind(IEditorService service) { _service = service; _service.RegisterCustomNotifier(this); _fs = (IFeatureSource)_service.GetEditedResource(); InitDefaults(); } internal void InitDefaults() { string xml = _fs.GetConfigurationContent(); if (!string.IsNullOrEmpty(xml)) { try { _conf = (GdalConfigurationDocument)ConfigurationDocument.LoadXml(xml); } catch { BuildDefaultDocument(); } lstView.Items.Clear(); List files = new List(); foreach (var loc in _conf.RasterLocations) { AddRasterItems(loc.Location, loc.Items); } } } private void AddRasterItems(string dir, GdalRasterItem[] items) { foreach (var item in items) { AddRasterItem(dir, item); } } private void AddRasterItem(string dir, GdalRasterItem item) { foreach (ListViewItem li in lstView.Items) { //A list view item of the same file name exist. Abort. if (((GdalRasterItem)li.Tag).FileName == item.FileName) return; } ListViewItem lvi = new ListViewItem(); lvi.Name = Path.Combine(dir, item.FileName); lvi.Text = lvi.Name; lvi.Tag = item; lvi.ImageIndex = 0; lstView.Items.Add(lvi); } // This should really come from GetSchemaMapping, but it's broken: minX, minY, maxX, maxY private const string TEMPLATE_CFG = "dynamic0.0010000.001000System generated default FDO Spatial ContextDefault{0} {1}{2} {3}" + "DefaultLOCAL_CS[\"*XY-MT*\",LOCAL_DATUM[\"*X-Y*\",10000],UNIT[\"Meter\", 1],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]geographic" + "" + ""; private void BuildDefaultDocument() { _conf = (GdalConfigurationDocument)ConfigurationDocument.LoadXml(string.Format(TEMPLATE_CFG, -10000000, -10000000, 10000000, 10000000)); } private void btnDelete_Click(object sender, EventArgs e) { List files = new List(); List items = new List(); foreach (ListViewItem item in lstView.SelectedItems) { items.Add(item); files.Add(item.Text); } DoUpdateConfiguration(new string[0], files.ToArray()); foreach (var it in items) { lstView.Items.Remove(it); } } private void lstView_SelectedIndexChanged(object sender, EventArgs e) { //btnRefresh.Enabled = btnDelete.Enabled = (lstView.SelectedItems.Count > 0); } private void btnRebuild_Click(object sender, EventArgs e) { BuildDefaultDocument(); List files = new List(); foreach (ListViewItem item in lstView.Items) { files.Add(item.Text); } lstView.Clear(); //Clear now. It will be repopulated after rebuild DoUpdateConfiguration(files.ToArray(), new string[0]); } private void browseFilesToolStripMenuItem_Click(object sender, EventArgs e) { if (openFileDialog.ShowDialog() == DialogResult.OK) { DoUpdateConfiguration(openFileDialog.FileNames, new string[0]); } } private void DoUpdateConfiguration(string[] toAdd, string[] toRemove) { DoUpdateConfiguration(toAdd, toRemove, false); } private void DoUpdateConfiguration(string[] toAdd, string[] toRemove, bool isAlias) { if (_conf == null) BuildDefaultDocument(); var pdlg = new ProgressDialog(); pdlg.CancelAbortsThread = true; var worker = new ProgressDialog.DoBackgroundWork(UpdateConfigurationDocument); var result = (UpdateConfigResult)pdlg.RunOperationAsync(null, worker, _conf, _fs.CurrentConnection, toAdd, toRemove, isAlias); if (result.Added.Count > 0 || result.Removed.Count > 0) { _fs.SetConfigurationContent(_conf.ToXml()); List remove = new List(); foreach (ListViewItem lvi in lstView.Items) { if (result.Removed.Contains(lvi.Text)) remove.Add(lvi); } foreach (var added in result.Added) { string dir = null; string fileName = null; if (isAlias) { dir = added.Substring(0, added.LastIndexOf("\\")); fileName = added.Substring(added.LastIndexOf("\\") + 1); } else { dir = Path.GetDirectoryName(added); fileName = Path.GetFileName(added); } foreach (var loc in _conf.RasterLocations) { if (loc.Location == dir) { foreach (var item in loc.Items) { if (item.FileName == fileName) { AddRasterItem(dir, item); } } } } } OnResourceChanged(); } } class UpdateConfigResult { public List Added { get; set; } public List Removed { get; set; } } object UpdateConfigurationDocument(BackgroundWorker worker, DoWorkEventArgs e, params object[] args) { GdalConfigurationDocument conf = (GdalConfigurationDocument)args[0]; IServerConnection conn = (IServerConnection)args[1]; string [] toAdd = args[2] as string[]; string [] toRemove = args[3] as string[]; bool isAlias = (bool)args[4]; worker.ReportProgress(0, Properties.Resources.UpdatingConfiguration); int total = toAdd.Length + toRemove.Length; int unit = (total / 100); int progress = 0; var result = new UpdateConfigResult() { Added = new List(), Removed = new List() }; //Remove first foreach (var remove in toRemove) { string dir = null; if (isAlias) { dir = remove.Substring(0, remove.LastIndexOf("\\")); } else { dir = Path.GetDirectoryName(remove); } var loc = FindLocation(conf, dir); if (null != loc) { string f = isAlias ? remove.Substring(remove.LastIndexOf("\\") + 1) : Path.GetFileName(remove); loc.RemoveItem(f); result.Removed.Add(remove); if (loc.Items.Length == 0) conf.RemoveLocation(loc); } progress += unit; worker.ReportProgress(progress, string.Format(Properties.Resources.ProcessedItem, remove)); } //Then add foreach (var add in toAdd) { string dir = null; if (isAlias) { dir = add.Substring(0, add.LastIndexOf("/")); } else { dir = Path.GetDirectoryName(add); } var loc = conf.AddLocation(dir); //Create a temp feature source to attempt interrogation of extents var values = new NameValueCollection(); values["DefaultRasterFileLocation"] = add; var fs = ObjectFactory.CreateFeatureSource(conn, "OSGeo.Gdal", values); var resId = new ResourceIdentifier("Session:" + conn.SessionID + "//" + Guid.NewGuid() + ".FeatureSource"); fs.ResourceID = resId.ToString(); conn.ResourceService.SaveResource(fs); var scList = fs.GetSpatialInfo(false); var raster = new GdalRasterItem() { FileName = isAlias ? add.Substring(add.LastIndexOf("/") + 1) : Path.GetFileName(add) }; if (scList.SpatialContext.Count > 0) { raster.MinX = Convert.ToDouble(scList.SpatialContext[0].Extent.LowerLeftCoordinate.X, CultureInfo.InvariantCulture); raster.MinY = Convert.ToDouble(scList.SpatialContext[0].Extent.LowerLeftCoordinate.Y, CultureInfo.InvariantCulture); raster.MaxX = Convert.ToDouble(scList.SpatialContext[0].Extent.UpperRightCoordinate.X, CultureInfo.InvariantCulture); raster.MaxY = Convert.ToDouble(scList.SpatialContext[0].Extent.UpperRightCoordinate.Y, CultureInfo.InvariantCulture); } else { raster.MinX = -10000000; raster.MinY = -10000000; raster.MaxX = 10000000; raster.MaxY = 10000000; } loc.AddItem(raster); result.Added.Add(Path.Combine(dir, raster.FileName)); progress += unit; worker.ReportProgress(progress, string.Format(Properties.Resources.ProcessedItem, add)); } //Re-calculate combined extent for spatial context var env = conf.CalculateExtent(); if (env != null) conf.SpatialContexts[0].Extent = env; return result; } private static GdalRasterLocationItem FindLocation(GdalConfigurationDocument conf, string directory) { foreach (var loc in conf.RasterLocations) { if (loc.Location == directory) return loc; } return null; } private void browseFolderToolStripMenuItem_Click(object sender, EventArgs e) { if (folderBrowserDialog.ShowDialog() == DialogResult.OK) { List files = new List(); files.AddRange(Directory.GetFiles(folderBrowserDialog.SelectedPath, "*.png")); files.AddRange(Directory.GetFiles(folderBrowserDialog.SelectedPath, "*.jpg")); files.AddRange(Directory.GetFiles(folderBrowserDialog.SelectedPath, "*.jpeg")); files.AddRange(Directory.GetFiles(folderBrowserDialog.SelectedPath, "*.tif")); files.AddRange(Directory.GetFiles(folderBrowserDialog.SelectedPath, "*.tiff")); files.AddRange(Directory.GetFiles(folderBrowserDialog.SelectedPath, "*.ecw")); files.AddRange(Directory.GetFiles(folderBrowserDialog.SelectedPath, "*.sid")); files.AddRange(Directory.GetFiles(folderBrowserDialog.SelectedPath, "*.dem")); files.AddRange(Directory.GetFiles(folderBrowserDialog.SelectedPath, "*.gif")); files.AddRange(Directory.GetFiles(folderBrowserDialog.SelectedPath, "*.bmp")); DoUpdateConfiguration(files.ToArray(), new string[0]); } } private void browseAliasedFileToolStripMenuItem_Click(object sender, EventArgs e) { using (var picker = new UnmanagedFileBrowser(_service.ResourceService)) { picker.AllowMultipleSelection = true; if (picker.ShowDialog() == DialogResult.OK) { DoUpdateConfiguration(picker.SelectedItems, new string[0], true); } } } private void browseAliasedFolderToolStripMenuItem_Click(object sender, EventArgs e) { using (var picker = new UnmanagedFileBrowser(_service.ResourceService)) { picker.AllowMultipleSelection = false; picker.SelectFoldersOnly = true; if (picker.ShowDialog() == DialogResult.OK) { List files = new List(); var folder = picker.SelectedItem; if (!string.IsNullOrEmpty(folder)) { folder = folder.Replace("%MG_DATA_PATH_ALIAS[", "[") .Replace("]%", "]"); } var list = _service.ResourceService.EnumerateUnmanagedData(folder, string.Empty, false, UnmanagedDataTypes.Files); var extensions = new List(new string[] { ".png", ".jpg", ".jpeg", ".tif", ".tiff", ".ecw", ".sid", ".dem", ".gif", ".bmp" }); foreach (var f in list.Items) { var file = f as OSGeo.MapGuide.ObjectModels.Common.UnmanagedDataListUnmanagedDataFile; if (file != null) { foreach (var ext in extensions) { if (file.FileName.ToLower().EndsWith(ext)) { var leftpart = file.UnmanagedDataId.Substring(0, file.UnmanagedDataId.IndexOf("]")); var rightpart = file.UnmanagedDataId.Substring(file.UnmanagedDataId.IndexOf("]") + 1); var item = "%MG_DATA_PATH_ALIAS" + leftpart + "]%" + rightpart; files.Add(item); break; } } } } DoUpdateConfiguration(files.ToArray(), new string[0], true); } } } } }