using FastReport.Utils; using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace FastReport.FastQueryBuilder { internal partial class TableView : UserControl, ITableView { private enum Mode { None, Border, Caption, Button1, Button2, Button3 } private int frameWidth = 3; private int captionHeight = 19; private int buttonWidth = 12; private int gapSize = 4; private Mode mode; private Point oldPos = new Point(0, 0); private Point minSize = new Point(50, 20); private TableBorder myBorder; private Table table; private Size oldSize; private FqbCheckedListBox checkedListBox1; public TableView() { BackColor = SystemColors.AppWorkspace; Size = new Size(150, 200); myBorder = new TableBorder(this); checkedListBox1 = new FqbCheckedListBox(); checkedListBox1.AllowDrop = true; checkedListBox1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; checkedListBox1.BorderStyle = BorderStyle.None; checkedListBox1.CheckOnClick = true; checkedListBox1.IntegralHeight = false; checkedListBox1.Name = "checkedListBox1"; checkedListBox1.TabIndex = 1; checkedListBox1.ItemCheck += checkedListBox1_ItemCheck; checkedListBox1.DragOver += checkedListBox1_DragOver; checkedListBox1.DragDrop += checkedListBox1_DragDrop; checkedListBox1.MouseEnter += checkedListBox1_MouseEnter; checkedListBox1.VertScrollValueChanged += checkedListBox1_Scroll; checkedListBox1.Parent = this; SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true); } #region Public Members public event EventHandler OnChangeAlias; public event CheckFieldEventHandler OnSelectField; public event AddLinkEventHandler OnAddLink; public event AddTableEventHandler OnDeleteTable; public void SetTableName(string tableName) { Text = tableName; } public Table Table { get { return table; } set { table = value; SetTableName(table.getNameAndAlias()); checkedListBox1.Items.Add('*'); foreach (Field fld in table.FieldList) { checkedListBox1.Items.Add(fld); } } } public Point GetPosition(Field field, LinkPosition lp) { int pos = checkedListBox1.FindString(field.ToString()); Rectangle rec = checkedListBox1.GetItemRectangle(pos); Point pnt = new Point(); pnt.Y = rec.Top + rec.Height / 2; if (pnt.Y < 0) pnt.Y = 0; else if (pnt.Y > checkedListBox1.Height) pnt.Y = checkedListBox1.Height; int _10 = this.LogicalToDevice(10); if (lp == LinkPosition.Left) pnt.X = -_10; else pnt.X = checkedListBox1.Width + _10; return new Point(pnt.X + checkedListBox1.Left + Left, pnt.Y + checkedListBox1.Top + Top); } public int GetLeft() => Left; public int GetWidth() => Width; public bool SelectCheckBox(string fieldName, string function, string alias) { for (int i = 0; i < checkedListBox1.Items.Count; i++) { var f = checkedListBox1.Items[i] as Field; if (f != null && f.Name == fieldName) { if (!String.IsNullOrEmpty(function)) f.Func = function; if (!String.IsNullOrEmpty(alias)) f.Alias = alias; checkedListBox1.SetItemChecked(i, true); return true; } } return false; } public void UpdateDpiDependencies() { frameWidth = this.LogicalToDevice(3); captionHeight = this.LogicalToDevice(20); buttonWidth = this.LogicalToDevice(12); gapSize = this.LogicalToDevice(4); checkedListBox1.Top = frameWidth + captionHeight; checkedListBox1.Left = frameWidth; checkedListBox1.Width = ClientRectangle.Width - 2 * frameWidth; checkedListBox1.Height = ClientRectangle.Height - captionHeight - frameWidth * 2; } #endregion private void checkedListBox1_DragOver(object sender, DragEventArgs e) { TableView _sender = (sender as Control).Parent as TableView; int n = _sender.checkedListBox1.IndexFromPoint(_sender.checkedListBox1.PointToClient(new Point(e.X, e.Y))); if (n == -1) { e.Effect = DragDropEffects.None; return; } Field _sended = _sender.checkedListBox1.Items[n] as Field; Field _current = (Field)e.Data.GetData(typeof(Field)); if (_current != null && _current.CanLink(_sended)) e.Effect = DragDropEffects.Copy; else e.Effect = DragDropEffects.None; } private void checkedListBox1_DragDrop(object sender, DragEventArgs e) { TableView _sender = (sender as Control).Parent as TableView; int n = _sender.checkedListBox1.IndexFromPoint(_sender.checkedListBox1.PointToClient(new Point(e.X, e.Y))); if (n == -1) { e.Effect = DragDropEffects.None; return; } Field _sended = _sender.checkedListBox1.Items[n] as Field; Field _current = (Field)e.Data.GetData(typeof(Field)); if (_current.CanLink(_sended)) { OnAddLink?.Invoke(sender, new AddLinkEventArgs(_current, _sended)); if (Parent != null) Parent.Refresh(); } } private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) { if (OnSelectField != null) { if (checkedListBox1.Items[e.Index] is Field) { Field field = checkedListBox1.Items[e.Index] as Field; CheckFieldEventArgs e2 = new CheckFieldEventArgs(field); e2.value = e.NewValue == CheckState.Checked; OnSelectField(sender, e2); checkedListBox1.ItemCheck -= checkedListBox1_ItemCheck; checkedListBox1.SetItemChecked(0, false); checkedListBox1.ItemCheck += checkedListBox1_ItemCheck; } else { for (int i = 1; i < checkedListBox1.Items.Count; i++) { checkedListBox1.SetItemChecked(i, e.NewValue == CheckState.Checked); } } } } private void checkedListBox1_Scroll(object sender, EventArgs e) { Parent?.Refresh(); } private void checkedListBox1_MouseEnter(object sender, EventArgs e) { myBorder.SelectedBorder = BorderPosition.None; mode = Mode.None; RefreshCaption(); } private void RefreshCaption() { Invalidate(false); } private void Button1Click() { if (Height <= captionHeight + frameWidth * 2) Height = oldSize.Height; else { oldSize = this.Size; Height = captionHeight + frameWidth * 2; } Parent.Refresh(); } private void Button2Click() { using (var box = new InputBox()) { box.TextBox.Text = table.Alias; if (box.ShowDialog() == DialogResult.OK) { OnChangeAlias?.Invoke(this, EventArgs.Empty); table.Alias = box.TextBox.Text; Text = table.getNameAndAlias(); } } } private void Button3Click() { this.Dispose(); OnDeleteTable?.Invoke(this, new AddTableEventArgs(this.table, new Point())); } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (e.Button == MouseButtons.Left) { if (mode == Mode.Border) { switch (myBorder.SelectedBorder) { case BorderPosition.Top: if (Height - e.Y >= minSize.Y) SetBounds(Left, Top + e.Y, Width, Height - e.Y); break; case BorderPosition.Bottom: if (Height - (oldPos.Y - e.Y) >= minSize.Y) Height -= oldPos.Y - e.Y; break; case BorderPosition.Left: if (Width - e.X >= minSize.X) SetBounds(Left + e.X, Top, Width - e.X, Height); break; case BorderPosition.Right: if (Width - (oldPos.X - e.X) >= minSize.X) Width -= oldPos.X - e.X; break; } oldPos.X = e.X; oldPos.Y = e.Y; Parent.Refresh(); } else if (mode == Mode.Caption) { Left += e.X - oldPos.X; Top += e.Y - oldPos.Y; } } else { mode = Mode.None; // check border if (e.X >= Width - frameWidth && e.X <= Width) myBorder.SelectedBorder = BorderPosition.Right; else if (e.X >= 0 && e.X <= frameWidth) myBorder.SelectedBorder = BorderPosition.Left; else if (e.Y >= 0 && e.Y <= frameWidth) myBorder.SelectedBorder = BorderPosition.Top; else if (e.Y >= Height - frameWidth && e.Y <= Height) myBorder.SelectedBorder = BorderPosition.Bottom; else myBorder.SelectedBorder = BorderPosition.None; if (myBorder.SelectedBorder != BorderPosition.None) mode = Mode.Border; else { if (e.Y < captionHeight + frameWidth) { // check buttons int x = Width - frameWidth; int w = buttonWidth + gapSize * 2; if (e.X >= x - w && e.X <= x) mode = Mode.Button3; x -= w; if (e.X >= x - w && e.X <= x) mode = Mode.Button2; x -= w; if (e.X >= x - w && e.X <= x) mode = Mode.Button1; // it's a caption if (mode == Mode.None) mode = Mode.Caption; RefreshCaption(); } } } } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); oldPos.X = e.X; oldPos.Y = e.Y; } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (mode == Mode.Button1) Button1Click(); else if (mode == Mode.Button2) Button2Click(); else if (mode == Mode.Button3) Button3Click(); } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); mode = Mode.None; RefreshCaption(); } protected override void OnLocationChanged(EventArgs e) { base.OnLocationChanged(e); Parent?.Refresh(); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); var g = e.Graphics; g.SmoothingMode = SmoothingMode.HighQuality; // caption var captionRect = new Rectangle(frameWidth, frameWidth, Width - frameWidth * 2, captionHeight); g.FillRectangle(SystemBrushes.Control, captionRect); captionRect.Offset(this.LogicalToDevice(2), 0); TextRenderer.DrawText(g, Text, Font, captionRect, SystemColors.WindowText, TextFormatFlags.VerticalCenter); // buttons int x = Width - frameWidth - gapSize - buttonWidth; int y = frameWidth + gapSize; int sz = buttonWidth + gapSize * 2; float _1 = this.LogicalToDevice(1f); float _2 = this.LogicalToDevice(2f); float _6 = this.LogicalToDevice(6f); var pen = new Pen(Color.Black, _1); var whitePen = new Pen(Color.White, _1); // button3 var p = pen; if (mode == Mode.Button3) { g.FillRectangle(Brushes.Firebrick, new Rectangle(x - gapSize, y - gapSize, sz, sz)); p = whitePen; } g.DrawLine(p, x + _2, y + _2, x + buttonWidth - _2, y + buttonWidth - _2); g.DrawLine(p, x + _2, y + buttonWidth - _2, x + buttonWidth - _2, y + _2); // button2 x -= sz; if (mode == Mode.Button2) g.FillRectangle(Brushes.White, new Rectangle(x - gapSize, y - gapSize, sz, sz)); g.DrawRectangle(pen, x + _1 * 2, y + _6, 1, 1); g.DrawRectangle(pen, x + _1 * 6, y + _6, 1, 1); g.DrawRectangle(pen, x + _1 * 10, y + _6, 1, 1); // button1 x -= sz; if (mode == Mode.Button1) g.FillRectangle(Brushes.White, new Rectangle(x - gapSize, y - gapSize, sz, sz)); g.DrawLine(pen, x + _1, y + _6, x + buttonWidth - _2, y + _6); pen.Dispose(); whitePen.Dispose(); } } }