#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; class SchemaNodeTag { public string SchemaName { get; set; } public bool Loaded { get; set; } public SchemaNodeTag(string name) { this.SchemaName = name; this.Loaded = false; } } class ClassNodeTag { public string SchemaName { get; set; } public string ClassName { get; set; } public string QualifiedName { get { return this.SchemaName + ":" + this.ClassName; } } public ClassDefinition Class { get; set; } public bool Loaded { get; set; } public ClassNodeTag(string schemaName, string className) { this.SchemaName = schemaName; this.ClassName = className; this.Loaded = false; } } /// /// Reloads the tree. /// /// The fs id. /// The caps. public void ReloadTree(string fsId, FdoProviderCapabilities caps) { currentFsId = fsId; _caps = caps; ClearPreviewPanes(); trvSchema.Nodes.Clear(); string[] schemaNames = _fsvc.GetSchemas(currentFsId); foreach (var s in schemaNames) { var schemaNode = new TreeNode(s); schemaNode.Tag = new SchemaNodeTag(s); schemaNode.ImageIndex = schemaNode.SelectedImageIndex = IDX_SCHEMA; schemaNode.Nodes.Add(Strings.TextLoading); trvSchema.Nodes.Add(schemaNode); } } private static void UpdateClassNode(TreeNode classNode, ClassDefinition cls) { //var classNode = new TreeNode(cls.Name); classNode.Nodes.Clear(); classNode.Name = cls.Name; classNode.Text = cls.Name; var clsTag = classNode.Tag as ClassNodeTag; if (clsTag == null) { classNode.Tag = new ClassNodeTag(cls.Parent.Name, cls.Name) { Loaded = true, Class = cls }; } else { clsTag.Loaded = true; clsTag.Class = cls; } classNode.ImageIndex = classNode.SelectedImageIndex = IDX_CLASS; classNode.ToolTipText = string.Format(Strings.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(Strings.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(Strings.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(Strings.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); } } 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 = Strings.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 = Strings.StandardQuery + " - " + cls.QualifiedName; //NOXLATE 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) { var tag = trvSchema.SelectedNode.Tag as ClassNodeTag; if (tag != null) return tag.Class; } return null; } private void trvSchema_AfterSelect(object sender, TreeViewEventArgs e) { switch (e.Node.Level) { case 1: //Class var cls = e.Node.Tag as ClassNodeTag; if (cls != null && cls.Class != null) { btnStandard.Enabled = true; btnSql.Enabled = this.SupportsSQL; } else { btnStandard.Enabled = false; btnSql.Enabled = false; } 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); } } private void trvSchema_AfterExpand(object sender, TreeViewEventArgs e) { var schTag = e.Node.Tag as SchemaNodeTag; var clsTag = e.Node.Tag as ClassNodeTag; if (schTag != null) { if (schTag.Loaded) return; e.Node.Nodes.Clear(); var classNames = _fsvc.GetClassNames(currentFsId, schTag.SchemaName); foreach (var qClsName in classNames) { var clsName = qClsName.Split(':')[1]; //NOXLATE var node = new TreeNode(clsName); node.Text = clsName; node.Tag = new ClassNodeTag(schTag.SchemaName, clsName); node.ImageIndex = node.SelectedImageIndex = IDX_CLASS; node.Nodes.Add(Strings.TextLoading); e.Node.Nodes.Add(node); } schTag.Loaded = true; } else if (clsTag != null) { if (clsTag.Loaded) return; var cls = _fsvc.GetClassDefinition(currentFsId, clsTag.QualifiedName); clsTag.Class = cls; UpdateClassNode(e.Node, cls); } } } }