using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Clifton.Tools.Strings.Extensions;
using MyXaml.Core;
using ROPLib;
using ROPLib.Data;
using ROPLib.Graphing;
using ROPLib.Interfaces;
using Interfaces.UI;
namespace IDE
{
public class ModelEditor
{
[MyXamlAutoInitialize]
IGrid dgvModel = null;
[MyXamlAutoInitialize]
ComboBox cbRootLevelEntity = null;
[MyXamlAutoInitialize]
TextBox tbNavigation = null;
[MyXamlAutoInitialize]
ComboBox cbMasterTables = null;
[MyXamlAutoInitialize]
ComboBox cbDetailTables = null;
public BindingContext BindingContext { get; set; }
public Form Form { get; set; }
protected bool ignoreRootChange = false;
protected DataSet dataSet;
public void SetDataSet(DataSet ds)
{
dataSet = ds;
dgvModel.AutoGenerateColumns = false;
dgvModel.DataSource = dataSet;
}
public void SetEntities(List<string> entityNames)
{
cbRootLevelEntity.DataSource = entityNames;
}
private void cbRootLevelEntity_SelectedIndexChanged(object sender, EventArgs e)
{
string entity = cbRootLevelEntity.SelectedItem.ToString();
SetRootLevelEntity(entity);
InitializeColumns();
if (!ignoreRootChange)
{
NavigateFrom(entity);
}
UpdateCaption(entity);
}
private void btnNavigateToMaster_Click(object sender, EventArgs e)
{
string entity = cbMasterTables.SelectedItem.ToString();
UpdateGrid(entity);
ShowNavigateToMaster(entity);
ClearRowFilter(entity);
}
private void btnNavigateToDetail_Click(object sender, EventArgs e)
{
string entity = cbDetailTables.SelectedItem.ToString();
UpdateGrid(entity);
ShowNavigateToDetail(entity);
ClearRowFilter(entity);
}
private void btnBack_Click(object sender, EventArgs e)
{
string qualifier;
string navItem = PopNavigation(out qualifier);
UpdateGrid(navItem);
SetRowFilter(navItem, qualifier);
}
protected void ClearRowFilter(string entity)
{
DataView dv = (DataView)((CurrencyManager)BindingContext[dataSet, entity]).List;
dv.RowFilter = String.Empty;
}
protected void SetRowFilter(string entity, string qualifier)
{
DataView dv = (DataView)((CurrencyManager)BindingContext[dataSet, entity]).List;
dv.RowFilter = qualifier.ToString();
}
protected string PopNavigation(out string qualifier)
{
qualifier = String.Empty;
string nav = tbNavigation.Text;
string[] navList = nav.Split('\r');
string ret = navList[0]; // Can't pop past the first item.
// Go back one level (0 indexed, so we subtract 2), however, because the nav text always has a trailing \r\n, we need to subtract 3!
int n = navList.Length - 3;
if (n >= 0)
{
string navItem = navList[n].Trim();
// If this not the root entity, it will be preceded with " <-- " or " --> ", but the leading whitespace is already trimmed.
if ((navItem[0] == '<') || (navItem[0] == '-'))
{
navItem = navItem.RightOf(' ');
}
// Left of any qualifier.
ret = navItem.LeftOf('[').Trim();
qualifier = navItem.Between('[', ']');
// Rebuild the navigation list (seems easier than finding the next to last \r\n)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < navList.Length - 2; i++)
{
sb.Append(navList[i].Trim());
sb.Append("\r\n");
}
tbNavigation.Text = sb.ToString();
}
return ret;
}
protected void InitializeMasterEntityList(string entity)
{
List<string> masterList = Schema.Instance.GetMasterEntities(entity);
cbMasterTables.DataSource = masterList;
if (masterList.Count == 0)
{
cbMasterTables.Text = String.Empty;
}
}
protected void InitializeDetailEntityList(string entity)
{
List<string> detailList = Schema.Instance.GetDetailEntities(entity);
cbDetailTables.DataSource = detailList;
if (detailList.Count == 0)
{
cbDetailTables.Text = String.Empty;
}
}
protected void SetRootLevelEntity(string entity)
{
dgvModel.DataMember = entity;
InitializeMasterEntityList(entity);
InitializeDetailEntityList(entity);
}
/// <summary>
/// Always clears the navigation list and starts over.
/// </summary>
protected void NavigateFrom(string entity)
{
tbNavigation.Text = entity + "\r\n";
ClearRowFilter(entity);
}
protected void ShowNavigateToMaster(string masterEntity)
{
tbNavigation.Text = tbNavigation.Text + " --> " + masterEntity + "\r\n";
}
protected void ShowNavigateToDetail(string detailEntity)
{
tbNavigation.Text = tbNavigation.Text + " <-- " + detailEntity + "\r\n";
}
protected void ShowNavigateToMaster(string masterEntity, string qualifier)
{
tbNavigation.Text = tbNavigation.Text + " --> " + masterEntity + " [" + qualifier + "]\r\n";
}
protected void ShowNavigateToDetail(string detailEntity, string qualifier)
{
tbNavigation.Text = tbNavigation.Text + " <-- " + detailEntity + " [" + qualifier + "]\r\n";
}
protected void UpdateCaption(string text)
{
Form.Text = text;
}
/// <summary>
/// Manually populate the columns as either textboxes or combobox controls.
/// </summary>
protected void InitializeColumns()
{
dgvModel.ClearColumns();
DataTable dt = dataSet.Tables[dgvModel.DataTableName];
foreach (IDataColumn dc in dt.Columns)
{
bool isLookup = false;
// Look at all the parent relations
foreach (DataRelation dr in dt.ParentRelations)
{
// If the current column has a parent relation...
if (dr.ChildColumns.Contains((DataColumn)dc))
{
DataView dvParent = new DataView(dr.ParentTable);
string displayField = Schema.Instance.GetEntity(dr.ParentTable.TableName).DisplayField;
if (String.IsNullOrEmpty(displayField))
{
displayField = dr.ParentTable.PrimaryKey[0].ColumnName;
}
dvParent.Sort = displayField;
dgvModel.AddLookupColumn(dvParent, dr.ParentTable.PrimaryKey[0].ColumnName, displayField, (DataColumn)dc);
isLookup = true;
break;
}
}
ROPLib.Attribute attr = Schema.Instance.GetAttribute(dc.AttributeName);
if (!isLookup)
{
// If the attribute associated with this column is an application entity lookup, then map this to a lookup control.
if (attr.HasApplicationLookup)
{
EntityProvider entityProvider = new EntityProvider(dataSet);
entityProvider.InitializeWithApplicationEntity(attr.EntityName);
entityProvider.LoadTable();
string displayMember = entityProvider.GetColumnNameMapping(attr.DisplayMember);
string valueMember = attr.ValueMember; // assumes "ID", not requiring a lookup.
DataTable dtSource = entityProvider.DataTable;
DataView dvSource = new DataView(dtSource);
dvSource.Sort = displayMember;
dgvModel.AddLookupColumn(dvSource, valueMember, displayMember, (DataColumn)dc);
isLookup = true;
}
}
if (!isLookup)
{
// If the attribute associated with this column is a model entity lookup, then map this to a lookup control.
if (attr.HasModelLookup)
{
string displayMember = attr.DisplayMember;
string valueMember = attr.ValueMember; // assumes "ID", not requiring a lookup.
DataTable dtSource = dataSet.Tables[attr.ModelEntityName];
DataView dvSource = new DataView(dtSource);
dvSource.Sort = displayMember;
dgvModel.AddLookupColumn(dvSource, valueMember, displayMember, (DataColumn)dc);
isLookup = true;
}
}
if (!isLookup)
{
if (attr.HasPickList)
{
List<ListItem> items = Schema.Instance.GetListItems(attr.PickList);
DataTable dtSource = ConvertToTable(items);
DataView dvSource = new DataView(dtSource);
dvSource.Sort = "Ordinality";
dgvModel.AddLookupColumn(dvSource, "Name", "Name", (DataColumn)dc);
isLookup = true;
}
}
if (!isLookup)
{
dgvModel.AddColumn((DataColumn)dc);
}
}
dgvModel.AdjustColumnWidths();
}
protected DataTable ConvertToTable(List<ListItem> items)
{
DataTable dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Ordinality", typeof(int));
foreach (ListItem item in items)
{
DataRow row = dt.NewRow();
row["Name"] = item.Name;
row["Ordinality"] = item.Ordinality;
dt.Rows.Add(row);
}
return dt;
}
private void btnSelectedMasters_Click(object sender, EventArgs e)
{
string currentEntity = dgvModel.DataMember;
string navToEntity = cbMasterTables.SelectedItem.ToString();
List<DataRow> selectedRows = dgvModel.SelectedRows;
StringBuilder qualifier = new StringBuilder();
string orRow = String.Empty;
if (selectedRows.Count > 0)
{
foreach (DataRow gridRow in selectedRows)
{
string orRelationship = String.Empty;
// Build qualifier: "[PK]=[value]"
foreach (DataRelation dr in dataSet.Relations)
{
if ((dr.ParentTable.TableName == navToEntity) && (dr.ChildTable.TableName == currentEntity))
{
string pkField = dr.ParentTable.PrimaryKey[0].ColumnName;
string fkField = dr.ChildColumns[0].ColumnName;
// Undefined relationship fields will not have an FK.
// Could also check for DBNull.Value.
if (!String.IsNullOrEmpty(gridRow[fkField].ToString()))
{
qualifier.Append(orRow);
qualifier.Append(orRelationship);
qualifier.Append(pkField);
qualifier.Append("=");
qualifier.Append(gridRow[fkField].ToString());
orRelationship = " or ";
orRow = String.Empty;
}
}
}
orRow = " or ";
}
UpdateGrid(navToEntity);
SetRowFilter(navToEntity, qualifier.ToString());
ShowNavigateToMaster(navToEntity, qualifier.ToString());
}
}
private void btnSelectedDetails_Click(object sender, EventArgs e)
{
List<DataRow> selectedRows = dgvModel.SelectedRows;
string orRow = String.Empty;
string currentEntity = dgvModel.DataMember;
string navToEntity = cbDetailTables.SelectedItem.ToString();
StringBuilder qualifier = new StringBuilder();
if (selectedRows.Count > 0)
{
foreach (DataRow gridRow in selectedRows)
{
string orRelationship = String.Empty;
// Build qualifier: "[FK]=[value]"
foreach (DataRelation dr in dataSet.Relations)
{
if ((dr.ChildTable.TableName == navToEntity) && (dr.ParentTable.TableName == currentEntity))
{
qualifier.Append(orRow);
qualifier.Append(orRelationship);
qualifier.Append(dr.ChildColumns[0].ColumnName);
qualifier.Append("=");
string pkField = dr.ParentTable.PrimaryKey[0].ColumnName;
qualifier.Append(gridRow[pkField].ToString());
orRelationship = " or ";
orRow = String.Empty;
}
}
orRow = " or ";
}
UpdateGrid(navToEntity);
SetRowFilter(navToEntity, qualifier.ToString());
// Doesn't work. Not the right view.
// dataSet.Tables[navToEntity].DefaultView.RowFilter = qualifier.ToString();
// Doesn't work. Not the right view.
// dataSet.DefaultViewManager.DataViewSettings[navToEntity].RowFilter = qualifier.ToString();
ShowNavigateToDetail(navToEntity, qualifier.ToString());
}
}
protected void UpdateGrid(string entity)
{
ignoreRootChange = true;
cbRootLevelEntity.SelectedItem = entity;
Application.DoEvents();
ignoreRootChange = false;
}
protected void OnSizeChanged(object sender, EventArgs args)
{
// Not required when attached to a DevExpress LayoutControlItem.
((Control)dgvModel).Height = ((Form)sender).Height - 340;
}
}
}