using System; using System.Windows.Forms; using System.Drawing; using System.Drawing.Drawing2D; using FastReport.Utils; using FastReport.Dialog; using FastReport.Design.ToolWindows; using FastReport.Data; namespace FastReport.Design.PageDesigners.Dialog { internal class DialogWorkspace : DesignWorkspaceBase { #region Fields #endregion #region Properties public static Grid Grid = new Grid(); public static bool ShowGrid; public static bool SnapToGrid; public DialogPage Page { get { return PageDesigner.Page as DialogPage; } } public override Point Offset { get { Point offset = Page.Form.ClientAreaOffset(); int _10 = this.LogicalToDevice(10); offset.X += _10; offset.Y += _10; return offset; } } #endregion #region Private Methods private void UpdateName() { if (Page.Name == "") Text = Page.ClassName + (Page.ZOrder + 1).ToString(); else Text = Page.Name; } private RectangleF GetSelectedRect() { RectangleF result = new RectangleF(100000, 100000, -100000, -100000); foreach (Base obj in Designer.SelectedObjects) { if (obj is ComponentBase) { ComponentBase c = obj as ComponentBase; if (c.Left < result.Left) result.X = c.Left; if (c.Right > result.Right) result.Width = c.Right - result.Left; if (c.Top < result.Top) result.Y = c.Top; if (c.Bottom > result.Bottom) result.Height = c.Bottom - result.Top; } else if (obj is DialogPage) { result = new RectangleF(0, 0, Page.Form.FrameSize().Width, Page.Form.FrameSize().Height); } } return result; } private void UpdateStatusBar() { RectangleF selectedRect = GetSelectedRect(); bool IsPageOrReportSelected = Designer.SelectedObjects.IsPageSelected || Designer.SelectedObjects.IsReportSelected; string location = IsPageOrReportSelected ? "" : selectedRect.Left.ToString() + "; " + selectedRect.Top.ToString(); string size = IsPageOrReportSelected ? "" : selectedRect.Width.ToString() + "; " + selectedRect.Height.ToString(); Designer.ShowStatus(location, size, "", ""); } private void AfterDragDrop(Point location) { DataFilterBaseControl control = Designer.SelectedObjects[0] as DataFilterBaseControl; if (control is TextBoxControl) { // show menu with different control types ContextMenuStrip menu = new ContextMenuStrip(); menu.Renderer = Config.DesignerSettings.ToolStripRenderer; Type[] controlTypes = new Type[] { typeof(TextBoxControl), typeof(MaskedTextBoxControl), typeof(ComboBoxControl), typeof(CheckedListBoxControl), typeof(ListBoxControl), typeof(DataSelectorControl) }; foreach (Type controlType in controlTypes) { ObjectInfo info = RegisteredObjects.FindObject(controlType); ToolStripMenuItem item = new ToolStripMenuItem(Res.Get(info.Text), Designer.GetImage(info.ImageIndex)); menu.Items.Add(item); item.Tag = controlType; item.Click += new EventHandler(ControlTypeItem_Click); } menu.Show(this, new Point((int)control.AbsLeft + Offset.X, (int)control.AbsBottom + Offset.Y)); } else { // look for another controls of same type in a form that bound to the same DataColumn // and setup the FilterOperation foreach (Base c in Page.AllObjects) { if (c != control && c.GetType() == control.GetType() && (c as DataFilterBaseControl).DataColumn == control.DataColumn) { (c as DataFilterBaseControl).FilterOperation = FilterOperation.GreaterThanOrEqual; control.FilterOperation = FilterOperation.LessThanOrEqual; Designer.SetModified(this, "Change"); break; } } } } private void ControlTypeItem_Click(object sender, EventArgs e) { DataFilterBaseControl control = Designer.SelectedObjects[0] as DataFilterBaseControl; Type controlType = (sender as ToolStripMenuItem).Tag as Type; DataFilterBaseControl newControl = Activator.CreateInstance(controlType) as DataFilterBaseControl; newControl.Parent = control.Parent; newControl.Location = control.Location; newControl.DataColumn = control.DataColumn; newControl.ReportParameter = control.ReportParameter; control.Dispose(); newControl.CreateUniqueName(); Designer.SelectedObjects.Clear(); Designer.SelectedObjects.Add(newControl); Designer.SetModified(this, "Insert"); } private void DrawSelectionRect(FRPaintEventArgs e) { RectangleF rect = NormalizeSelectionRect(); IGraphics g = e.Graphics; Brush b = Report.GraphicCache.GetBrush(Color.FromArgb(80, SystemColors.Highlight)); g.FillRectangle(b, rect.Left, rect.Top, rect.Width, rect.Height); Pen pen = Report.GraphicCache.GetPen(SystemColors.Highlight, 1, DashStyle.Dash); g.DrawRectangle(pen, rect.Left, rect.Top, rect.Width, rect.Height); } #endregion #region Protected Methods protected override float GridSnapSize { get { return Grid.SnapSize; } } protected override bool CheckGridStep() { bool al = SnapToGrid; if ((ModifierKeys & Keys.Alt) > 0) al = !al; bool result = true; float kx = eventArgs.delta.X; float ky = eventArgs.delta.Y; if (al) { result = kx >= GridSnapSize || kx <= -GridSnapSize || ky >= GridSnapSize || ky <= -GridSnapSize; if (result) { kx = (int)(kx / GridSnapSize) * GridSnapSize; ky = (int)(ky / GridSnapSize) * GridSnapSize; } } else { result = kx != 0 || ky != 0; } eventArgs.delta.X = kx; eventArgs.delta.Y = ky; return result; } protected override void OnPaint(PaintEventArgs e) { if (Locked || Page == null || Report == null) return; // add extra room to fit tooltip int _100 = this.LogicalToDevice(100); #if AVALONIA // do not alter size in the paint event Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(() => Size = new Size(Page.Form.FrameSize().Width + _100, Page.Form.FrameSize().Height + _100)); #else Size = new Size(Page.Form.FrameSize().Width + _100, Page.Form.FrameSize().Height + _100); #endif Graphics g = e.Graphics; FRPaintEventArgs paintArgs = new FRPaintEventArgs(g, 1, 1, Report.GraphicCache); // check if workspace is active (in the mdi mode). ObjectCollection objects = Designer.Objects; if (Designer.ActiveReport != Report) { objects = Page.AllObjects; objects.Add(Page); } // draw form int _10 = this.LogicalToDevice(10); Page.SetDesigning(true); g.DrawImage(Page.FormBitmap, _10, _10); g.TranslateTransform(Offset.X, Offset.Y); if (ShowGrid) Grid.Draw(e.Graphics, new Rectangle(0, 0, (int)Page.ClientSize.Width, (int)Page.ClientSize.Height)); // draw objects foreach (Base obj in objects) { if (obj is ComponentBase) { obj.SetDesigning(true); (obj as ComponentBase).Draw(paintArgs); } } // draw selection if (!mouseDown && Designer.ActiveReport == Report) { foreach (Base obj in Designer.SelectedObjects) { if (obj is ComponentBase) (obj as ComponentBase).DrawSelection(paintArgs); } } virtualGuides.Draw(g); if (mode2 == WorkspaceMode2.SelectionRect) DrawSelectionRect(paintArgs); DrawToolTip(g); } protected override void ShowLocationSizeToolTip(int x, int y) { string s = ""; RectangleF selectedRect = GetSelectedRect(); if (mode2 == WorkspaceMode2.Move) s = selectedRect.Left.ToString() + "; " + selectedRect.Top.ToString(); else if (mode2 == WorkspaceMode2.Size) s = selectedRect.Width.ToString() + "; " + selectedRect.Height.ToString(); ShowToolTip(s, x, y); } protected override void OnDragOver(DragEventArgs drgevent) { base.OnDragOver(drgevent); if (!Designer.cmdInsert.Enabled) { drgevent.Effect = DragDropEffects.None; return; } if (mode1 != WorkspaceMode1.DragDrop) { DictionaryWindow.DraggedItem item = DictionaryWindow.DragUtils.GetOne(drgevent); if (item == null) return; Type dataType = null; if (item.obj is Column) dataType = (item.obj as Column).DataType; else if (item.obj is Parameter) dataType = (item.obj as Parameter).DataType; else return; // determine type of control to insert Type controlType = typeof(NumericUpDownControl); if (dataType == typeof(string) || dataType == typeof(char)) controlType = typeof(TextBoxControl); else if (dataType == typeof(DateTime) || dataType == typeof(TimeSpan)) controlType = typeof(DateTimePickerControl); else if (dataType == typeof(bool)) controlType = typeof(CheckBoxControl); else if (dataType == typeof(byte[])) controlType = null; if (controlType == null) { drgevent.Effect = DragDropEffects.None; return; } // create label and control bool needCreateLabel = controlType != typeof(CheckBoxControl); if (needCreateLabel) { Designer.InsertObject(new ObjectInfo[] { RegisteredObjects.FindObject(controlType), RegisteredObjects.FindObject(typeof(LabelControl)) }, InsertFrom.Dictionary); } else { Designer.InsertObject(RegisteredObjects.FindObject(controlType), InsertFrom.Dictionary); } // setup control datafiltering DataFilterBaseControl control = Designer.SelectedObjects[0] as DataFilterBaseControl; control.Top += (16 / Grid.SnapSize) * Grid.SnapSize; if (item.obj is Column) control.DataColumn = item.text; else if (item.obj is Parameter) control.ReportParameter = item.text; // setup label text string labelText = ""; if (item.obj is Column) labelText = (item.obj as Column).Alias; else if (item.obj is Parameter) { labelText = (item.obj as Parameter).Description; if (String.IsNullOrEmpty(labelText)) labelText = (item.obj as Parameter).Name; } if (needCreateLabel) { LabelControl label = Designer.SelectedObjects[1] as LabelControl; label.Text = labelText; } else control.Text = labelText; eventArgs.DragSource = control; } mode1 = WorkspaceMode1.DragDrop; Point pt = PointToClient(new Point(drgevent.X, drgevent.Y)); OnMouseMove(new MouseEventArgs(MouseButtons.Left, 0, pt.X, pt.Y, 0)); drgevent.Effect = drgevent.AllowedEffect; } protected override void OnDragDrop(DragEventArgs drgevent) { base.OnDragDrop(drgevent); DictionaryWindow.DraggedItem item = DictionaryWindow.DragUtils.GetOne(drgevent); if (item == null) return; Point pt = PointToClient(new Point(drgevent.X, drgevent.Y)); OnMouseUp(new MouseEventArgs(MouseButtons.Left, 0, pt.X, pt.Y, 0)); if (eventArgs.DragSource != null) AfterDragDrop(pt); } protected override void OnDragLeave(EventArgs e) { base.OnDragLeave(e); CancelPaste(); } #endregion #region Public Methods public override float GetScale() { return 1; } protected override Base GetParentForPastedObjects() { return Page; } public override void Paste(ObjectCollection list, InsertFrom source) { base.Paste(list, source); // scale if necessary if (source != InsertFrom.Clipboard) { foreach (Base c in list) { if (c is DialogControl) { float scale = this.Dpi() / 96f; (c as DialogControl).Control.Scale(new SizeF(scale, scale)); } } } // find left-top edge of inserted objects float minLeft = 100000; float minTop = 100000; foreach (Base c in list) { if (c is ComponentBase) { ComponentBase c1 = c as ComponentBase; if (c1.Left < minLeft) minLeft = c1.Left; if (c1.Top < minTop) minTop = c1.Top; } } foreach (Base c in list) { // correct the left-top if (c is ComponentBase) { ComponentBase c1 = c as ComponentBase; c1.Left -= minLeft + Grid.SnapSize * 1000; c1.Top -= minTop + Grid.SnapSize * 1000; if (c1.Width == 0 && c1.Height == 0) { SizeF preferredSize = c1.GetPreferredSize(); c1.Width = preferredSize.Width; c1.Height = preferredSize.Height; if (SnapToGrid) { c1.Width = (int)Math.Round(c1.Width / Grid.SnapSize) * Grid.SnapSize; c1.Height = (int)Math.Round(c1.Height / Grid.SnapSize) * Grid.SnapSize; } } } } mode1 = WorkspaceMode1.Insert; mode2 = WorkspaceMode2.Move; eventArgs.activeObject = null; int _10 = this.LogicalToDevice(10); OnMouseDown(new MouseEventArgs(MouseButtons.Left, 0, Offset.X + _10 - (int)(Grid.SnapSize * 1000), Offset.Y + _10 - (int)(Grid.SnapSize * 1000), 0)); } public override void Refresh() { // FR.Net issue with PanelX: called from constructor when PageDesigner is not set yet if (PageDesigner == null) return; UpdateStatusBar(); base.Refresh(); } #endregion public DialogWorkspace(PageDesignerBase pageDesigner) : base(pageDesigner) { SnapToGrid = true; BackColor = SystemColors.Window; } } }