using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; #pragma warning disable 1591 namespace OSGeo.MapGuide.Viewer { /// /// A dialog for displaying feature query results in a grid /// public partial class MgQueryResultsDialog : Form { private string _geomProp; private string[] _identityProps; private MgReader _reader; private IMapViewer _viewer; private Dictionary _propMap; private MgLayerBase _layer; private int _limit; private string[] _columns; public MgQueryResultsDialog(IMapViewer viewer, MgLayerBase layer, MgReader reader, int limit) { InitializeComponent(); _viewer = viewer; _reader = reader; _geomProp = layer.GetFeatureGeometryName(); _layer = layer; _limit = limit; _propMap = new Dictionary(); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); bgGridLoader.RunWorkerAsync(_reader); } private void bgGridLoader_DoWork(object sender, DoWorkEventArgs e) { var reader = (MgReader)e.Argument; var wktRw = new MgWktReaderWriter(); var agfRw = new MgAgfReaderWriter(); var cls = _layer.GetClassDefinition(); var idProps = cls.GetIdentityProperties(); var idNames = new List(); for (int i = 0; i < idProps.Count; i++) { var prop = idProps.GetItem(i); idNames.Add(prop.Name); } _identityProps = idNames.ToArray(); var propNames = new List(); int propCount = reader.GetPropertyCount(); //.net 2.0 compatibility hack for set-like behaviour var skipProps = new Dictionary(); for (int i = 0; i < propCount; i++) { var pt = reader.GetPropertyType(i); if (pt == MgPropertyType.Blob || pt == MgPropertyType.Clob || pt == MgPropertyType.Feature || pt == MgPropertyType.Null || pt == MgPropertyType.Raster) { skipProps[i] = i; } else { var name = reader.GetPropertyName(i); _propMap.Add(name, pt); propNames.Add(name); } } try { bgGridLoader.ReportProgress(-1, new InitGridAction() { ColumnNames = propNames.ToArray() }); int read = 0; while (reader.ReadNext()) { object[] values = new object[propCount]; for (int i = 0; i < propCount; i++) { if (skipProps.ContainsKey(i)) continue; if (reader.IsNull(i)) { values[i] = null; } else { switch (reader.GetPropertyType(i)) { case MgPropertyType.Boolean: values[i] = reader.GetBoolean(i); break; case MgPropertyType.Byte: values[i] = reader.GetByte(i); break; case MgPropertyType.DateTime: values[i] = ToClrDateTime(reader.GetDateTime(i)); break; case MgPropertyType.Decimal: case MgPropertyType.Double: values[i] = reader.GetDouble(i); break; case MgPropertyType.Geometry: { try { var agf = reader.GetGeometry(i); var geom = agfRw.Read(agf); var env = geom.Envelope(); var envLL = env.LowerLeftCoordinate; var envUR = env.UpperRightCoordinate; var wkt = wktRw.Write(geom); values[i] = new BoxedGeometry() { Text = wkt, GeomBounds = new Bounds() { LowerX = envLL.X, LowerY = envLL.Y, UpperX = envUR.X, UpperY = envUR.Y } }; } catch { values[i] = null; } } break; case MgPropertyType.Int16: values[i] = reader.GetInt16(i); break; case MgPropertyType.Int32: values[i] = reader.GetInt32(i); break; case MgPropertyType.Int64: values[i] = reader.GetInt64(i); break; case MgPropertyType.Single: values[i] = reader.GetSingle(i); break; case MgPropertyType.String : values[i] = reader.GetString(i); break; } } } bgGridLoader.ReportProgress(-1, new AddRow() { Values = values }); read++; if ((_limit > 0 && read >= _limit)) break; } } finally { reader.Close(); wktRw.Dispose(); agfRw.Dispose(); wktRw = null; agfRw = null; } } private void bgGridLoader_ProgressChanged(object sender, ProgressChangedEventArgs e) { var action = (Progress)e.UserState; if (action.Action == ProgressAction.InitGrid) { var columns = ((InitGridAction)action).ColumnNames; for (int i = 0; i < columns.Length; i++) { grdResults.Columns.Add(columns[i], columns[i]); } _columns = columns; } else { grdResults.Rows.Add(((AddRow)action).Values); } } private void bgGridLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { lblResults.Text = string.Format(Strings.CountResults, grdResults.Rows.Count); } static DateTime ToClrDateTime(MgDateTime dt) { return new DateTime(dt.Year, dt.Day, dt.Month, dt.Hour, dt.Minute, dt.Second, dt.Microsecond / 1000); } abstract class Progress { public abstract ProgressAction Action { get; } } class InitGridAction : Progress { public override ProgressAction Action { get { return ProgressAction.InitGrid; } } public string[] ColumnNames { get; set; } } class AddRow : Progress { public override ProgressAction Action { get { return ProgressAction.AddRow; } } public object[] Values { get; set; } } enum ProgressAction { InitGrid, AddRow } private void grdResults_SelectionChanged(object sender, EventArgs e) { btnZoom.Enabled = btnSelect.Enabled = (grdResults.SelectedRows.Count > 0); } private void btnSelect_Click(object sender, EventArgs e) { _viewer.ClearSelection(); var sel = _viewer.GetSelection(); foreach (DataGridViewRow row in grdResults.SelectedRows) { MgPropertyCollection idProps = new MgPropertyCollection(); foreach (string name in _identityProps) { int idx = Array.IndexOf(_columns, name); if (idx >= 0) { int type = _propMap[name]; switch (type) { case MgPropertyType.Boolean: idProps.Add(new MgBooleanProperty(name, Convert.ToBoolean(row.Cells[idx].Value))); break; case MgPropertyType.Byte: idProps.Add(new MgByteProperty(name, Convert.ToByte(row.Cells[idx].Value))); break; case MgPropertyType.DateTime: idProps.Add(new MgDateTimeProperty(name, FromClrDateTime((DateTime)row.Cells[idx].Value))); break; case MgPropertyType.Decimal: case MgPropertyType.Double: idProps.Add(new MgDoubleProperty(name, Convert.ToDouble(row.Cells[idx].Value))); break; case MgPropertyType.Int16: idProps.Add(new MgInt16Property(name, Convert.ToInt16(row.Cells[idx].Value))); break; case MgPropertyType.Int32: idProps.Add(new MgInt32Property(name, Convert.ToInt32(row.Cells[idx].Value))); break; case MgPropertyType.Int64: idProps.Add(new MgInt64Property(name, Convert.ToInt64(row.Cells[idx].Value))); break; case MgPropertyType.Single: idProps.Add(new MgSingleProperty(name, Convert.ToSingle(row.Cells[idx].Value))); break; case MgPropertyType.String: idProps.Add(new MgStringProperty(name, Convert.ToString(row.Cells[idx].Value))); break; } } } if (idProps.Count == _identityProps.Length) { sel.AddFeatureIds(_layer, _layer.FeatureClassName, idProps); } else { idProps.Dispose(); idProps = null; } } _viewer.UpdateSelection(true); } static MgDateTime FromClrDateTime(DateTime dt) { return new MgDateTime((short)dt.Year, (short)dt.Month, (short)dt.Day, (short)dt.Hour, (short)dt.Minute, (short)dt.Second, dt.Millisecond * 1000); } private void btnZoom_Click(object sender, EventArgs e) { //Collect the bounding boxes of all geometries and zoom to that MgEnvelope env = new MgEnvelope(); int idx = Array.IndexOf(_columns, _geomProp); if (idx < 0) { MessageBox.Show(string.Format(Strings.ErrorGeometryPropertyNotFound, _geomProp)); return; } foreach (DataGridViewRow row in grdResults.SelectedRows) { var geom = row.Cells[idx].Value as BoxedGeometry; MgEnvelope tmp = new MgEnvelope(geom.GeomBounds.LowerX, geom.GeomBounds.LowerY, geom.GeomBounds.UpperX, geom.GeomBounds.UpperY); env.ExpandToInclude(tmp); } var ll = env.LowerLeftCoordinate; var ur = env.UpperRightCoordinate; _viewer.ZoomToExtents(ll.X, ll.Y, ur.X, ur.Y); } } internal struct Bounds { public double LowerX; public double LowerY; public double UpperX; public double UpperY; } internal class BoxedGeometry { public override string ToString() { return this.Text; } public string Text { get; set; } public Bounds GeomBounds { get; set; } } }