using FastReport.Data; using FastReport.Utils; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Windows.Forms; namespace FastReport.Forms { internal partial class RelationEditorForm : BaseDialogForm { private Relation relation; private void cbxParent_DrawItem(object sender, DrawItemEventArgs e) { e.DrawBackground(); if (e.Index >= 0) { DataSourceBase dataSource = (sender as ComboBox).Items[e.Index] as DataSourceBase; this.DrawImageAndText(e, this.GetImage(222), dataSource.Alias); } } private void cbxParent_SelectedIndexChanged(object sender, EventArgs e) { columnsPanel.ParentDataSource = cbxParent.SelectedItem as DataSourceBase; } private void cbxChild_SelectedIndexChanged(object sender, EventArgs e) { columnsPanel.ChildDataSource = cbxChild.SelectedItem as DataSourceBase; } private void columnsPanel_Resize(object sender, EventArgs e) { ClientSize = new Size(ClientSize.Width, columnsPanel.Bottom + this.LogicalToDevice(50)); } private void RelationEditorForm_FormClosing(object sender, FormClosingEventArgs e) { if (DialogResult == DialogResult.OK) { string[] parentColumns = columnsPanel.ParentColumns; string[] childColumns = columnsPanel.ChildColumns; e.Cancel = !(parentColumns.Length > 0 && parentColumns.Length == childColumns.Length); if (e.Cancel) FRMessageBox.Error(Res.Get("Forms,RelationEditor,Error")); } } private void RelationEditorForm_FormClosed(object sender, FormClosedEventArgs e) { Done(); } private void Init() { Dictionary dictionary = relation.Report.Dictionary; ObjectCollection allObjects = dictionary.AllObjects; SortedList tables = new SortedList(); foreach (Base c in allObjects) { if (c is DataSourceBase) { DataSourceBase table = c as DataSourceBase; if (!tables.ContainsKey(table.Alias)) tables.Add(table.Alias, table); } } foreach (KeyValuePair keyValue in tables) { DataSourceBase table = keyValue.Value; cbxParent.Items.Add(table); cbxChild.Items.Add(table); } cbxParent.SelectedItem = relation.ParentDataSource; cbxChild.SelectedItem = relation.ChildDataSource; if (relation.ParentColumns != null && relation.ChildColumns != null && relation.ParentColumns.Length == relation.ChildColumns.Length) { for (int i = 0; i < relation.ParentColumns.Length; i++) { columnsPanel.AddPanel(relation.ParentColumns[i], relation.ChildColumns[i]); } } columnsPanel.EnsureSinglePanel(); } private void Done() { if (DialogResult == DialogResult.OK) { relation.ParentDataSource = columnsPanel.ParentDataSource; relation.ChildDataSource = columnsPanel.ChildDataSource; relation.ParentColumns = columnsPanel.ParentColumns; relation.ChildColumns = columnsPanel.ChildColumns; } } public override void Localize() { base.Localize(); MyRes res = new MyRes("Forms,RelationEditor"); Text = res.Get(""); lblParentTable.Text = res.Get("ParentTable"); lblChildTable.Text = res.Get("ChildTable"); lblColumns.Text = res.Get("Columns"); } public override void UpdateDpiDependencies() { base.UpdateDpiDependencies(); cbxParent.ItemHeight = cbxChild.ItemHeight = this.LogicalToDevice(16); columnsPanel.UpdateDpiDependencies(); } public RelationEditorForm(Relation relation) { this.relation = relation; InitializeComponent(); Localize(); UIUtils.CheckRTL(this); UpdateDpiDependencies(); Init(); } } internal class ColumnsPanel : Panel { private List panels; private DataSourceBase parentDataSource; private DataSourceBase childDataSource; [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public DataSourceBase ParentDataSource { get => parentDataSource; set { parentDataSource = value; panels.ForEach(p => p.ParentDataSource = value); } } [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public DataSourceBase ChildDataSource { get => childDataSource; set { childDataSource = value; panels.ForEach(p => p.ChildDataSource = value); } } public string[] ParentColumns => panels.Select(p => p.ParentColumn).Where(x => !string.IsNullOrEmpty(x)).ToArray(); public string[] ChildColumns => panels.Select(p => p.ChildColumn).Where(x => !string.IsNullOrEmpty(x)).ToArray(); private void UpdateSize() { Height = panels.Sum(p => p.Height); } private ColumnPanel AddEmptyPanel(ColumnPanel sender) { var panel = new ColumnPanel() { ParentDataSource = ParentDataSource, ChildDataSource = ChildDataSource }; if (sender == null) panels.Add(panel); else panels.Insert(panels.IndexOf(sender) + 1, panel); Controls.Add(panel); Controls.SetChildIndex(panel, sender == null ? 0 : Controls.IndexOf(sender)); panel.Scale(new SizeF(this.DpiMultiplier(), this.DpiMultiplier())); UIUtils.CheckRTL(panel); panel.UpdateDpiDependencies(); panel.Focus(); UpdateSize(); return panel; } private void RemovePanel(ColumnPanel panel) { if (panels.Count > 1) { panels.Remove(panel); panel.Dispose(); UpdateSize(); } else { panel.ParentColumn = null; panel.ChildColumn = null; } } public void AddPanel(string parentColumn, string childColumn) { var panel = AddEmptyPanel(null); panel.ParentColumn = parentColumn; panel.ChildColumn = childColumn; } public void EnsureSinglePanel() { if (panels.Count == 0) AddPanel("", ""); } public void UpdateDpiDependencies() => panels.ForEach(p => p.UpdateDpiDependencies()); public ColumnsPanel() { panels = new List(); Size = new Size(445, 150); } private class ColumnPanel : Panel { private ComboBox cbxParentColumn; private ComboBox cbxChildColumn; private Button btnAdd; private Button btnRemove; private ColumnsPanel ParentPanel => Parent as ColumnsPanel; private DataSourceBase parentDataSource; public DataSourceBase ParentDataSource { get => parentDataSource; set { parentDataSource = value; FillColumns(value, cbxParentColumn); } } private DataSourceBase childDataSource; public DataSourceBase ChildDataSource { get => childDataSource; set { childDataSource = value; FillColumns(value, cbxChildColumn); } } public string ParentColumn { get => cbxParentColumn.Text; set => cbxParentColumn.Text = value; } public string ChildColumn { get => cbxChildColumn.Text; set => cbxChildColumn.Text = value; } private void FillColumns(DataSourceBase dataSource, ComboBox comboBox) { comboBox.Items.Clear(); if (dataSource == null) return; foreach (Column column in dataSource.Columns) { comboBox.Items.Add(column.Alias); } } private void btnAdd_Click(object sender, EventArgs e) { ParentPanel.AddEmptyPanel(this); } private void btnRemove_Click(object sender, EventArgs e) { ParentPanel.RemovePanel(this); } private void cbxParentColumn_DrawItem(object sender, DrawItemEventArgs e) { e.DrawBackground(); if (e.Index >= 0) { var column = ParentDataSource.Columns[e.Index]; this.DrawImageAndText(e, this.GetImage(column.GetImageIndex()), column.Alias); } } private void cbxChildColumn_DrawItem(object sender, DrawItemEventArgs e) { e.DrawBackground(); if (e.Index >= 0) { var column = ChildDataSource.Columns[e.Index]; this.DrawImageAndText(e, this.GetImage(column.GetImageIndex()), column.Alias); } } public void UpdateDpiDependencies() { btnAdd.Image = this.GetImage(213); btnRemove.Image = this.GetImage(51); cbxParentColumn.ItemHeight = cbxChildColumn.ItemHeight = this.LogicalToDevice(16); } public ColumnPanel() { Dock = DockStyle.Top; Height = 27; cbxParentColumn = new ComboBox(); cbxParentColumn.DrawMode = DrawMode.OwnerDrawFixed; cbxParentColumn.DropDownStyle = ComboBoxStyle.DropDownList; cbxParentColumn.Location = new Point(3, 3); cbxParentColumn.Size = new Size(175, 21); cbxParentColumn.DrawItem += cbxParentColumn_DrawItem; cbxChildColumn = new ComboBox(); cbxChildColumn.DrawMode = DrawMode.OwnerDrawFixed; cbxChildColumn.DropDownStyle = ComboBoxStyle.DropDownList; cbxChildColumn.Location = new Point(190, 3); cbxChildColumn.Size = new Size(175, 21); cbxChildColumn.DrawItem += cbxChildColumn_DrawItem; btnAdd = new Button(); btnAdd.FlatStyle = FlatStyle.Flat; btnAdd.FlatAppearance.BorderSize = 0; btnAdd.Location = new Point(372, 2); btnAdd.Size = new Size(23, 23); btnAdd.Click += btnAdd_Click; btnRemove = new Button(); btnRemove.FlatStyle = FlatStyle.Flat; btnRemove.FlatAppearance.BorderSize = 0; btnRemove.Location = new Point(394, 2); btnRemove.Size = new Size(23, 23); btnRemove.Click += btnRemove_Click; Controls.Add(btnRemove); Controls.Add(btnAdd); Controls.Add(cbxChildColumn); Controls.Add(cbxParentColumn); } } } }