#region Disclaimer / License // Copyright (C) 2010, 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.MaestroAPI.Services; using OSGeo.MapGuide.MaestroAPI; using OSGeo.MapGuide.ObjectModels.FeatureSource; using OSGeo.MapGuide.ObjectModels.Capabilities; using OSGeo.MapGuide.MaestroAPI.Schema; namespace Maestro.Editors.FeatureSource.Preview { /// /// A control that allows local previewing of a feature source /// public partial class LocalFeatureSourcePreviewCtrl : UserControl { /// /// Initializes a new instance of the class. /// public LocalFeatureSourcePreviewCtrl() { InitializeComponent(); } private IFeatureService _fsvc; /// /// Initializes this instance /// /// The feature service. public void Init(IFeatureService featureService) { _fsvc = featureService; } const int IDX_SCHEMA = 0; const int IDX_CLASS = 1; const int IDX_PROP = 2; const int IDX_IDENTITY = 3; const int IDX_GEOMETRY = 4; const int IDX_RASTER = 5; private string currentFsId; /// /// Gets or sets a value indicating whether [supports SQL]. /// /// true if [supports SQL]; otherwise, false. public bool SupportsSQL { get; set; } private FdoProviderCapabilities _caps; /// /// Reloads the tree. /// /// The fs id. /// The caps. public void ReloadTree(string fsId, FdoProviderCapabilities caps) { currentFsId = fsId; _caps = caps; ClearPreviewPanes(); trvSchema.Nodes.Clear(); //FIXME: Do this lazily ala. FDO Toolbox var schema = _fsvc.DescribeFeatureSource(currentFsId); Dictionary> classes = new Dictionary>(); foreach (var cls in schema.AllClasses) { string[] tokens = cls.QualifiedName.Split(':'); if (!classes.ContainsKey(tokens[0])) classes[tokens[0]] = new List(); classes[tokens[0]].Add(cls); } string[] schemaNames = schema.SchemaNames; foreach (var s in schemaNames) { var schemaNode = new TreeNode(s); schemaNode.Tag = s; schemaNode.ImageIndex = schemaNode.SelectedImageIndex = IDX_SCHEMA; trvSchema.Nodes.Add(schemaNode); if (classes.ContainsKey(s)) { foreach (var cls in classes[s]) { var classNode = new TreeNode(cls.Name); classNode.Text = cls.Name; classNode.Tag = cls; classNode.ImageIndex = classNode.SelectedImageIndex = IDX_CLASS; classNode.ToolTipText = string.Format(Properties.Resources.FsPreview_ClassNodeTooltip, cls.Name, cls.Description, cls.DefaultGeometryPropertyName, Environment.NewLine); foreach (var prop in cls.Properties) { var propNode = new TreeNode(prop.Name); propNode.Text = prop.Name; propNode.Tag = prop; if (prop.Type == PropertyDefinitionType.Geometry) { var g = (GeometricPropertyDefinition)prop; propNode.ImageIndex = propNode.SelectedImageIndex = IDX_GEOMETRY; propNode.ToolTipText = string.Format(Properties.Resources.FsPreview_GeometryPropertyNodeTooltip, g.Name, g.Description, g.GeometryTypesToString(), g.IsReadOnly, g.HasElevation, g.HasMeasure, g.SpatialContextAssociation, Environment.NewLine); } else if (prop.Type == PropertyDefinitionType.Data) { var d = (DataPropertyDefinition)prop; if (cls.IdentityProperties.Contains((DataPropertyDefinition)prop)) propNode.ImageIndex = propNode.SelectedImageIndex = IDX_IDENTITY; else propNode.ImageIndex = propNode.SelectedImageIndex = IDX_PROP; propNode.ToolTipText = string.Format(Properties.Resources.FsPreview_DataPropertyNodeTooltip, d.Name, d.Description, d.DataType.ToString(), d.IsNullable, d.IsReadOnly, d.Length, d.Precision, d.Scale, Environment.NewLine); } else if (prop.Type == PropertyDefinitionType.Raster) { var r = (RasterPropertyDefinition)prop; propNode.ImageIndex = propNode.SelectedImageIndex = IDX_RASTER; propNode.ToolTipText = string.Format(Properties.Resources.FsPreview_RasterPropertyNodeTooltip, r.Name, r.Description, r.IsNullable, r.DefaultImageXSize, r.DefaultImageYSize, r.SpatialContextAssociation, Environment.NewLine); } else { propNode.ImageIndex = propNode.SelectedImageIndex = IDX_PROP; } classNode.Nodes.Add(propNode); } schemaNode.Nodes.Add(classNode); } } } } private void btnRefresh_Click(object sender, EventArgs e) { ReloadTree(currentFsId, _caps); } private void btnSql_Click(object sender, EventArgs e) { var cls = GetSelectedClass(); if (cls != null) { AddPreviewPane(cls, QueryMode.SQL); } } private void btnStandard_Click(object sender, EventArgs e) { var cls = GetSelectedClass(); if (cls != null) { AddPreviewPane(cls, QueryMode.Standard); } } private void ClearPreviewPanes() { tabPreviews.TabPages.Clear(); hasSql = false; } private bool hasSql = false; void AddPreviewPane(ClassDefinition cls, QueryMode mode) { if (mode == QueryMode.SQL) { if (!hasSql) { var pane = new PreviewPane(currentFsId, mode, cls, _fsvc, _caps); var page = new TabPage(); page.Text = Properties.Resources.SQLQuery; page.Tag = mode; pane.Dock = DockStyle.Fill; page.Controls.Add(pane); tabPreviews.TabPages.Add(page); tabPreviews.SelectedIndex = tabPreviews.TabPages.IndexOf(page); hasSql = true; } } else { var pane = new PreviewPane(currentFsId, mode, cls, _fsvc, _caps); var page = new TabPage(); page.Text = Properties.Resources.StandardQuery + " - " + cls.QualifiedName; page.Tag = mode; pane.Dock = DockStyle.Fill; page.Controls.Add(pane); tabPreviews.TabPages.Add(page); tabPreviews.SelectedIndex = tabPreviews.TabPages.IndexOf(page); } btnClose.Enabled = (tabPreviews.TabPages.Count > 0); } ClassDefinition GetSelectedClass() { if (trvSchema.SelectedNode != null) { return trvSchema.SelectedNode.Tag as ClassDefinition; } return null; } private void trvSchema_AfterSelect(object sender, TreeViewEventArgs e) { switch (e.Node.Level) { case 1: //Class var cls = e.Node.Tag as ClassDefinition; if (cls != null) { btnStandard.Enabled = true; btnSql.Enabled = this.SupportsSQL; } break; default: btnStandard.Enabled = false; btnSql.Enabled = false; break; } } private void btnClose_Click(object sender, EventArgs e) { if (tabPreviews.SelectedIndex >= 0) { //This is almost the same tab removal logic from TabFactory.cs in Maestro.Base //done this way to remove any doubts about Mono int idx = -1; //HACK: Mono (2.4) will chuck a hissy fit if we remove //a tab from a TabControl that has a selected tab so we //have to null the selected tab, but this cause weird //visual effects once the tab is removed, so we record //the selected index, so we can assign the one beside it //to be the selected tab after removal. idx = tabPreviews.SelectedIndex; var tab = tabPreviews.TabPages[idx]; tabPreviews.SelectedTab = null; tabPreviews.TabPages.RemoveAt(idx); if ((QueryMode)tab.Tag == QueryMode.SQL) hasSql = false; if (idx > 0) { idx--; tabPreviews.SelectedIndex = idx; } else { //Set to first tab if available. if (tabPreviews.TabCount > 0) { tabPreviews.SelectedIndex = 0; } } btnClose.Enabled = (tabPreviews.TabPages.Count > 0); } } } }