using FastReport.Design.PageDesigners.Code; using FastReport.Design.ToolWindows; using FastReport.Forms; using FastReport.Preview; using FastReport.Utils; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace FastReport.Design { /// /// Represents the report's designer control. /// /// /// Usually you don't need to create an instance of this class. The designer can be called /// using the method of /// the instance. /// This control represents pure designer surface + Objects toolbar. If you need /// standard menu, statusbar, toolbars and tool windows, use the /// control instead. Also you may /// decide to use a designer's form () /// instead of a control. /// To run a designer, you need to attach a Report instance to it. This can be done via /// the property. /// To call the designer in MDI (Multi-Document Interface) mode, use the /// property. /// To set up some global properties, use the static class /// or component that you can use in the Visual Studio IDE. /// [ToolboxItem(false)] [Designer("FastReport.VSDesign.DesignerControlLayoutDesigner, FastReport.VSDesign, Version=1.0.0.0, Culture=neutral, PublicKeyToken=db7e5ce63278458c, processorArchitecture=MSIL")] public partial class Designer : UserControl, ISupportInitialize { #region Fields private Report report; private ReportTab activeReportTab; private PluginCollection plugins; private List recentFiles; private DesignerClipboard clipboard; private bool mdiMode; private List documents; private StartPageTab startPage; private ObjectCollection objects; private SelectedObjectCollection selectedObjects; private SelectedObjectCollection previouslySelectedObjects; private SelectedComponents selectedComponents; private SelectedReportComponents selectedReportComponents; private SelectedTextObjects selectedTextObjects; private LastFormatting lastFormatting; private bool modified; private bool formatPainter; private ReportComponentBase formatPainterPattern; private DesignerRestrictions restrictions; private bool isPreviewPageDesigner; private bool askSave; private string layoutState; private bool initFlag; private bool layoutNeeded; private UIStyle uIStyle; private StorageService designerStorage; private StorageService autoSaveStorage; private Timer autoSaveTimer; private TaskCompletionSource embeddedPreviewCompletion; private PreviewControl embeddedPreview; // tools private ObjectsToolbar objectsToolbar; private DictionaryWindow dataWindow; private PropertiesWindow propertiesWindow; private ReportTreeWindow reportTreeWindow; private MessagesWindow messagesWindow; // commands private NewCommand fcmdNew; private NewPageCommand fcmdNewPage; private NewDialogCommand fcmdNewDialog; private OpenCommand fcmdOpen; private OpenPageCommand fcmdOpenPage; private OpenViaCloudCommand fcmdOpenViaCloud; private SaveCommand fcmdSave; private SaveToCloudCommand fcmdSaveToCloud; private SaveAsCommand fcmdSaveAs; private SaveWithRandomDataCommand fcmdSaveWithRandomData; private SaveAllCommand fcmdSaveAll; private CloseCommand fcmdClose; private CloseAllCommand fcmdCloseAll; private PreviewCommand fcmdPreview; private PreviewCloudCommand fcmdPreviewCloud; private PrinterSettingsCommand fcmdPrinterSetup; private PageSettingsCommand fcmdPageSetup; private AddDataCommand fcmdAddData; private SortDataSourcesCommand fcmdSortDataSources; private ChooseDataCommand fcmdChooseData; private UndoCommand fcmdUndo; private RedoCommand fcmdRedo; private CutCommand fcmdCut; private CopyCommand fcmdCopy; private PasteCommand fcmdPaste; private FormatPainterCommand fcmdFormatPainter; private DeleteCommand fcmdDelete; private CopyPageCommand copyPageCommand; private DeletePageCommand fcmdDeletePage; private SelectAllCommand fcmdSelectAll; private GroupCommand fcmdGroup; private UngroupCommand fcmdUngroup; private EditCommand fcmdEdit; private FindCommand fcmdFind; private ReplaceCommand fcmdReplace; private BringToFrontCommand fcmdBringToFront; private SendToBackCommand fcmdSendToBack; private InsertCommand fcmdInsert; private InsertBandCommand fcmdInsertBand; private RecentFilesCommand fcmdRecentFiles; private SelectLanguageCommand fcmdSelectLanguage; private ViewStartPageCommand fcmdViewStartPage; private ReportSettingsCommand fcmdReportSettings; private OptionsCommand fcmdOptions; private ReportStylesCommand fcmdReportStyles; private ReportValidationCommand fcmdReportValidation; private HelpContentsCommand fcmdHelpContents; private AccountCommand fcmdAccount; private AboutCommand fcmdAbout; private WelcomeCommand fcmdWelcome; // polygon private PolygonSelectModeCommand fcmdPolySelectMove; private PolygonSelectModeCommand fcmdPolySelectPointer; private PolygonSelectModeCommand fcmdPolySelectAddPoint; private PolygonSelectModeCommand fcmdPolySelectBezier; private PolygonSelectModeCommand fcmdPolySelectRemovePoint; #endregion #region Properties /// /// Occurs when designer's UI state changed. /// public event EventHandler UIStateChanged; /// /// Gets or sets the edited report. /// /// /// To initialize the designer, you need to pass a Report instance to this property. /// This will create the designer's surface associated with the report. /// /// Designer designer = new Designer(); /// designer.Parent = form1; /// designer.Report = report1; /// /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Report Report { get { return report; } set { report = value; if (report != null) report.Designer = this; InitTabs(); } } /// /// Gets active report object. /// /// /// May be null if Start Page selected, or no reports opened. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Report ActiveReport { get { return activeReportTab == null ? null : activeReportTab.Report; } set { foreach (DocumentWindow c in Documents) { if (c is ReportTab && (c as ReportTab).Report == value) { c.Activate(); return; } } } } /// /// Gets a collection of global plugins such as menu, properties window, etc. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PluginCollection Plugins { get { return plugins; } } /// /// Gets a collection of objects on the active page of the active report. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ObjectCollection Objects { get { return objects; } } /// /// Gets a collection of selected objects on the active page of the active report. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SelectedObjectCollection SelectedObjects { get { return selectedObjects; } } /// /// Gets a collection of selected objects of the ComponentBase type. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SelectedComponents SelectedComponents { get { return selectedComponents; } } /// /// Gets a collection of selected objects of the ReportComponentBase type. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SelectedReportComponents SelectedReportComponents { get { return selectedReportComponents; } } /// /// Gets a collection of selected objects of the TextObject type. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SelectedTextObjects SelectedTextObjects { get { return selectedTextObjects; } } /// /// Gets or sets a value indicating that the report was modified. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool Modified { get { return modified; } set { modified = value; } } /// /// Gets or sets a value that determines whether to ask user to save changes when closing the designer. /// public bool AskSave { get { return askSave; } set { askSave = value; } } /// /// Gets the designer restrictions. /// public DesignerRestrictions Restrictions { get { return restrictions; } } /// /// Gets or sets a value indicating that designer is run in MDI mode. /// /// /// To call the designer in MDI (Multi-Document Interface) mode, use the following code: /// /// DesignerControl designer = new DesignerControl(); /// designer.MdiMode = true; /// designer.ShowDialog(); /// /// [DefaultValue(false)] public bool MdiMode { get { return mdiMode; } set { mdiMode = value; UpdateMdiMode(); } } /// /// Gets or sets the visual style. /// public UIStyle UIStyle { get { return uIStyle; } set { uIStyle = value; UpdateUIStyle(); UIStyleChanged?.Invoke(this, EventArgs.Empty); } } /// /// Occurs when the UIStyle property is changed. /// public event EventHandler UIStyleChanged; /// /// Gets a value indicating that designer is used to edit a preview page. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool IsPreviewPageDesigner { get { return isPreviewPageDesigner; } set { isPreviewPageDesigner = value; } } /// /// Gets or sets the zoom factor. /// public float Zoom { get { if (ActiveReportTab != null) return ActiveReportTab.Zoom; return 1; } set { if (ActiveReportTab != null) ActiveReportTab.Zoom = value; } } /// /// Gets the zoom factor with respect of designer's dpi value. /// public float ZoomDpi { get { return Zoom * this.DpiMultiplier(); } } /// /// The "File|New" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public NewCommand cmdNew { get { return fcmdNew; } } /// /// The "New Page" toolbar command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public NewPageCommand cmdNewPage { get { return fcmdNewPage; } } /// /// The "New Dialog" toolbar command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public NewDialogCommand cmdNewDialog { get { return fcmdNewDialog; } } /// /// The "File|Open|Open locally." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public OpenCommand cmdOpen { get { return fcmdOpen; } } /// /// The "File|Open|Open page." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public OpenPageCommand cmdOpenPage { get { return fcmdOpenPage; } } /// /// The "File|Open|Open via Cloud." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public OpenViaCloudCommand cmdOpenViaCloud { get { return fcmdOpenViaCloud; } } /// /// The "File|Save" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SaveCommand cmdSave { get { return fcmdSave; } } /// /// The "File|Save to Cloud" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SaveToCloudCommand cmdSaveToCloudCommand { get { return fcmdSaveToCloud; } } /// /// The "File|Save As..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SaveAsCommand cmdSaveAs { get { return fcmdSaveAs; } } /// /// The "File|Save With Random Data..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SaveWithRandomDataCommand cmdSaveWithRandomData { get { return fcmdSaveWithRandomData; } } /// /// The "File|Save All" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SaveAllCommand cmdSaveAll { get { return fcmdSaveAll; } } /// /// The "File|Close" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public CloseCommand cmdClose { get { return fcmdClose; } } /// /// The "Window|Close All" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public CloseAllCommand cmdCloseAll { get { return fcmdCloseAll; } } /// /// The "File|Preview..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PreviewCommand cmdPreview { get { return fcmdPreview; } } /// /// The "File|Preview on Cloud..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PreviewCloudCommand cmdPreviewCloud { get { return fcmdPreviewCloud; } } /// /// The "File|Printer Setup..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PrinterSettingsCommand cmdPrinterSetup { get { return fcmdPrinterSetup; } } /// /// The "File|Page Setup..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PageSettingsCommand cmdPageSetup { get { return fcmdPageSetup; } } /// /// The "Data|Add New Data Source..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public AddDataCommand cmdAddData { get { return fcmdAddData; } } /// /// The "Data|Sort Data Sources" command. /// public SortDataSourcesCommand cmdSortDataSources { get { return fcmdSortDataSources; } } /// /// The "Data|Choose Report Data..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ChooseDataCommand cmdChooseData { get { return fcmdChooseData; } } /// /// The "Edit|Undo" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public UndoCommand cmdUndo { get { return fcmdUndo; } } /// /// The "Edit|Redo" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public RedoCommand cmdRedo { get { return fcmdRedo; } } /// /// The "Edit|Cut" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public CutCommand cmdCut { get { return fcmdCut; } } /// /// The "Edit|Copy" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public CopyCommand cmdCopy { get { return fcmdCopy; } } /// /// The "Edit|Paste" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PasteCommand cmdPaste { get { return fcmdPaste; } } /// /// The "Format Painter" toolbar command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public FormatPainterCommand cmdFormatPainter { get { return fcmdFormatPainter; } } /// /// The "Edit|Delete" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public DeleteCommand cmdDelete { get { return fcmdDelete; } } /// /// The "Edit|Copy Page" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public CopyPageCommand cmdCopyPage { get { return copyPageCommand; } } /// /// The "Edit|Delete Page" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public DeletePageCommand cmdDeletePage { get { return fcmdDeletePage; } } /// /// The "Edit|Select All" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SelectAllCommand cmdSelectAll { get { return fcmdSelectAll; } } /// /// The "Edit|Group" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public GroupCommand cmdGroup { get { return fcmdGroup; } } /// /// The "Edit|Ungroup" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public UngroupCommand cmdUngroup { get { return fcmdUngroup; } } /// /// The "Edit" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public EditCommand cmdEdit { get { return fcmdEdit; } } /// /// The "Edit|Find..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public FindCommand cmdFind { get { return fcmdFind; } } /// /// The "Polygon move command" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PolygonSelectModeCommand CmdPolySelectMove { get { return fcmdPolySelectMove; } } /// /// The "Polygon point move" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PolygonSelectModeCommand CmdPolySelectPointer { get { return fcmdPolySelectPointer; } } /// /// The "Polygon add new point" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PolygonSelectModeCommand CmdPolySelectAddPoint { get { return fcmdPolySelectAddPoint; } } /// /// The "Polygon berier" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PolygonSelectModeCommand CmdPolySelectBezier { get { return fcmdPolySelectBezier; } } /// /// The "Polygon remove point" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public PolygonSelectModeCommand CmdPolySelectRemovePoint { get { return fcmdPolySelectRemovePoint; } } /// /// The "Edit|Replace..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ReplaceCommand cmdReplace { get { return fcmdReplace; } } /// /// The "Bring To Front" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public BringToFrontCommand cmdBringToFront { get { return fcmdBringToFront; } } /// /// The "Send To Back" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SendToBackCommand cmdSendToBack { get { return fcmdSendToBack; } } /// /// The "Insert" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public InsertCommand cmdInsert { get { return fcmdInsert; } } /// /// The "Insert Band" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public InsertBandCommand cmdInsertBand { get { return fcmdInsertBand; } } /// /// The "Recent Files" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public RecentFilesCommand cmdRecentFiles { get { return fcmdRecentFiles; } } /// /// The "File|Select Language..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SelectLanguageCommand cmdSelectLanguage { get { return fcmdSelectLanguage; } } /// /// The "View|Start Page" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ViewStartPageCommand cmdViewStartPage { get { return fcmdViewStartPage; } } /// /// The "Report|Options..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ReportSettingsCommand cmdReportSettings { get { return fcmdReportSettings; } } /// /// The "View|Options..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public OptionsCommand cmdOptions { get { return fcmdOptions; } } /// /// The "Report|Styles..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ReportStylesCommand cmdReportStyles { get { return fcmdReportStyles; } } /// /// The "Report|Validation" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ReportValidationCommand cmdReportValidation { get { return fcmdReportValidation; } } /// /// The "Help|Help Contents..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public HelpContentsCommand cmdHelpContents { get { return fcmdHelpContents; } } /// /// The "Help|Account" command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public AccountCommand cmdAccount { get { return fcmdAccount; } } /// /// The "Help|About..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public AboutCommand cmdAbout { get { return fcmdAbout; } } /// /// The "Show welcome window..." command. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public WelcomeCommand cmdWelcome { get { return fcmdWelcome; } } /// /// Gets or sets the layout state of the designer. /// /// /// This property is used to store layout in Visual Studio design time. You may also use /// it to save and restore the designer's layout in your code. However, consider using the /// and methods that use FastReport /// configuration file. /// [Browsable(false)] public string LayoutState { get { XmlDocument doc = new XmlDocument(); doc.Root.Name = "Config"; SaveDockState(doc.Root); using (MemoryStream stream = new MemoryStream()) { doc.Save(stream); return Encoding.UTF8.GetString(stream.ToArray()); } } set { layoutState = value; if (initFlag) layoutNeeded = true; else RestoreLayout(value); } } /// /// Fires when the layout is changed. /// /// /// This event is for internal use only. /// public event EventHandler LayoutChangedEvent; internal StartPageTab StartPage { get { return startPage; } } // active report tab. May be null if Start Page selected, or no reports opened internal ReportTab ActiveReportTab { get { return activeReportTab; } set { if (activeReportTab != value) { if (activeReportTab != null) activeReportTab.ReportDeactivated(); activeReportTab = value; if (value != null) value.ReportActivated(); else ClearSelection(); UpdatePlugins(null); } } } // list of recent opened files internal List RecentFiles { get { return recentFiles; } } internal List Documents { get { return documents; } } internal DesignerClipboard Clipboard { get { return clipboard; } } internal DictionaryWindow DataWindow { get { return dataWindow; } } internal PropertiesWindow PropertiesWindow { get { return propertiesWindow; } } internal ReportTreeWindow ReportTreeWindow { get { return reportTreeWindow; } } internal MessagesWindow MessagesWindow { get { return messagesWindow; } } internal CodePageDesigner Editor { get { return ActiveReportTab.Editor; } } internal LastFormatting LastFormatting { get { return lastFormatting; } } internal bool FormatPainter { get { return formatPainter; } set { if (formatPainter != value) { formatPainter = value; formatPainterPattern = value ? SelectedReportComponents.First : null; UpdatePlugins(null); } } } internal bool IsVSDesignMode { get { return DesignMode; } } internal Timer AutoSaveTimer { get { return autoSaveTimer; } } internal Dictionary CloudReportDictionary { get; set; } = new Dictionary(); #endregion #region Private Methods private void SetupAutoSave() { autoSaveStorage = new StorageService("Designer,Saving"); autoSaveTimer = new Timer(); autoSaveTimer.Interval = autoSaveStorage.GetInt("AutoSaveMinutes", 5) * 60000; autoSaveTimer.Tick += delegate (object s1, EventArgs e1) { if (this != null && !IsPreviewPageDesigner) { if (cmdSave.Enabled) { ActiveReportTab.AutoSaveFile(); } else { if (File.Exists(Config.AutoSaveFileName)) File.Delete(Config.AutoSaveFileName); if (File.Exists(Config.AutoSaveFile)) File.Delete(Config.AutoSaveFile); } } }; } /// /// Updates UI style of the designer. /// public virtual void UpdateUIStyle() { UpdateUIStyleInternal(); foreach (DocumentWindow document in Documents) { document.UpdateUIStyle(); } plugins.UpdateUIStyle(); } // create initial pages (Start Page, default report) private void InitTabs() { if (mdiMode) AddStartPageTab(); if (report != null) AddReportTab(CreateReportTab(report)); } private void AddDocument(DocumentWindow doc) { Documents.Add(doc); doc.AddToTabControl(tabs); doc.Activate(); } private void RemoveDocument(DocumentWindow doc) { if (doc is StartPageTab) startPage = null; Documents.Remove(doc); doc.Close(); } internal bool CloseDocument(DocumentWindow doc) { if (doc is ReportTab) { if (!(doc as ReportTab).CanClose()) return false; } RemoveDocument(doc); return true; } private void ClearSelection() { activeReportTab = null; Objects.Clear(); SelectedObjects.Clear(); SelectionChanged(null); UpdatePlugins(null); } #endregion #region Protected Methods /// /// Initializes designer plugins such as toolbars and toolwindows. /// protected virtual void InitPlugins() { InitTools(); plugins.AddRange(new IDesignerPlugin[] { objectsToolbar, dataWindow, propertiesWindow, reportTreeWindow, messagesWindow }); // add export plugins plugins.Add(typeof(ExportPlugins.FR3.FR3ExportPlugin)); #if MSCHART plugins.Add(typeof(ExportPlugins.RDL.RDLExportPlugin)); #endif // add import plugins #if MSCHART plugins.Add(typeof(ImportPlugins.RDL.RDLImportPlugin)); #endif plugins.Add(typeof(ImportPlugins.ListAndLabel.ListAndLabelImportPlugin)); plugins.Add(typeof(ImportPlugins.DevExpress.DevExpressImportPlugin)); plugins.Add(typeof(ImportPlugins.RTF.RTFImportPlugin)); plugins.Add(typeof(ImportPlugins.StimulSoft.StimulSoftImportPlugin)); plugins.Add(typeof(ImportPlugins.JasperReports.JasperReportsImportPlugin)); } #endregion #region Public Methods /// /// Zooms the report to page width. /// public void ZoomPageWidth() { if (ActiveReportTab != null) ActiveReportTab.ZoomPageWidth(); } /// /// Zooms the report to whole page. /// public void ZoomWholePage() { if (ActiveReportTab != null) ActiveReportTab.ZoomWholePage(); } /// /// Cancels paste mode. /// public void CancelPaste() { ActiveReportTab.ActivePageDesigner.CancelPaste(); } /// /// AutoSave system initialization. /// public void StartAutoSave() { if (IsPreviewPageDesigner) return; if (File.Exists(Config.AutoSaveFile) && File.Exists(Config.AutoSaveFileName) && autoSaveStorage.GetBool("EnableAutoSave", true) == true) { string filepath = File.ReadAllText(Config.AutoSaveFileName); using (LoadAutoSaveForm f = new LoadAutoSaveForm(filepath)) { if (f.ShowDialog() == DialogResult.OK) { ActiveReportTab.LoadAutoSaveFile(filepath); SetModified(); } } } if (File.Exists(Config.AutoSaveFileName)) File.Delete(Config.AutoSaveFileName); if (File.Exists(Config.AutoSaveFile)) File.Delete(Config.AutoSaveFile); autoSaveTimer.Enabled = autoSaveStorage.GetBool("EnableAutoSave", true); } /// /// Stops the AutoSave system. /// public void StopAutoSave() { if (IsPreviewPageDesigner) return; autoSaveTimer.Stop(); if (File.Exists(Config.AutoSaveFileName)) File.Delete(Config.AutoSaveFileName); if (File.Exists(Config.AutoSaveFile)) File.Delete(Config.AutoSaveFile); } /// /// Call this method if you change something in the report. /// /// /// This method adds the current report state to the undo buffer and updates all plugins. /// public void SetModified() { SetModified(null, "Change"); } /// /// Call this method if you change something in the report. /// /// The object that was modified. /// The undo action name. /// /// This method adds the current report state to the undo buffer and updates all plugins. /// public void SetModified(object sender, string action) { SetModified(sender, action, null); } /// /// Call this method if you change something in the report. /// /// The object that was modified. /// The undo action name. /// The name of modified object. public void SetModified(object sender, string action, string objName) { modified = true; if (ActiveReportTab != null) ActiveReportTab.SetModified(sender, action, objName); UpdatePlugins(sender); } /// /// Call this method to tell the designer that current selection is changed. /// /// The plugin that changes the selection (may be null). public void SelectionChanged(object sender) { // check groups ObjectCollection selectedObjects = new ObjectCollection(); SelectedObjects.CopyTo(selectedObjects); foreach (Base c in selectedObjects) { if (c is ComponentBase && (c as ComponentBase).GroupIndex != 0) { int groupIndex = (c as ComponentBase).GroupIndex; foreach (Base c1 in Objects) { if (c1 is ComponentBase && (c1 as ComponentBase).GroupIndex == groupIndex) { if (SelectedObjects.IndexOf(c1) == -1) SelectedObjects.Add(c1); } } } } foreach (Base c in previouslySelectedObjects) { c.SelectionChanged(); } foreach (Base c in selectedObjects) { c.SelectionChanged(); if (formatPainter && formatPainterPattern != null && c is ReportComponentBase) (c as ReportComponentBase).AssignFormat(formatPainterPattern); } SelectedComponents.Update(); SelectedReportComponents.Update(); SelectedTextObjects.Update(); if (ActiveReportTab != null) ActiveReportTab.Plugins.SelectionChanged(sender); plugins.SelectionChanged(sender); SelectedObjects.CopyTo(previouslySelectedObjects); if (formatPainter && formatPainterPattern != null) { if (sender != null) SetModified(); else { SetModified(null, "no-undo"); FormatPainter = false; } } OnUIStateChanged(); } /// /// Locks all plugins. /// /// /// This method is usually called when we destroy the report to prevent unexpected /// errors - such as trying to draw destroyed objects. /// public void Lock() { if (ActiveReportTab != null) ActiveReportTab.Plugins.Lock(); plugins.Lock(); } /// /// Unlocks all plugins. /// /// /// Call this method after the Lock. /// public void Unlock() { if (ActiveReportTab != null) ActiveReportTab.Plugins.Unlock(); plugins.Unlock(); } /// /// Call this method to refresh all plugins' content. /// /// The plugin that we don't need to refresh. public void UpdatePlugins(object sender) { if (ActiveReportTab != null) ActiveReportTab.Plugins.Update(sender); plugins.Update(sender); OnUIStateChanged(); } /// /// Updates localization of the designer. /// public void Localize() { Plugins.Localize(); if (ActiveReportTab != null) ActiveReportTab.Localize(); // Mono: update toolwindows captions & tabs LocalizeInternal(); } /// /// Updates layout and images on dpi change. /// /// The sender object. public virtual void UpdateDpiDependencies(object sender) { Plugins.UpdateDpiDependencies(sender); if (ActiveReportTab != null) ActiveReportTab.UpdateDpiDependencies(); // Mono: this should be after all plugins (TabStrip images related) UpdateDpiDependenciesInternal(); embeddedPreview?.UpdateDpiDependencies(); } /// /// Checks if parent window can be closed. /// /// The cancel event args. /// /// Use this method in the window's FormClosing event handler if you use this control. /// This method checks if the embedded preview is running and cancels it. Also if there is unsaved changes, the user will be asked to save changes. /// public void ParentFormClosing(FormClosingEventArgs e) { if (embeddedPreview != null) { if (embeddedPreview.IsAsyncReportRunning) embeddedPreview.Report.Abort(); else embeddedPreviewCompletion.SetResult(true); e.Cancel = true; return; } if (!CloseAll()) { e.Cancel = true; } } internal async Task ShowEmbeddedPreview(Report report) { PreviewControl savePreview = report.Preview; report.Preview = null; Config.ReportSettings.ShowProgress = false; bool finished = false; try { if (await report.AsyncPrepareStart()) // startup, compile, run dialogs. May throw a compiler exception { var preview = new PreviewControl(); preview.Buttons = Config.PreviewSettings.Buttons | PreviewButtons.Close; preview.Dock = DockStyle.Fill; #if !MONO preview.Size = Parent.ClientSize; // winforms, less flickering; Avalonia - wrong size on pmV2 #endif preview.Visible = false; // setup preview control preview.SetAsyncReportRunning(); report.Preview = preview; report.SetupPreviewControl(); preview.Parent = Parent; #if WPF // fix WPF rendering issues (pmV2) Application.DoEvents(); #endif #if !MONO preview.Scale(new System.Drawing.SizeF(this.FontDpiMultiplier(), this.FontDpiMultiplier())); #endif UIUtils.CheckRTL(preview); preview.UpdateDpiDependencies(); // swap designer and preview Parent.SuspendLayout(); foreach (Control c in Parent.Controls) c.Visible = false; preview.Visible = true; #if (WPF || AVALONIA) var form = FindForm().window as IForm; form.ExtendedAppArea = false; form.ExtendedAppAreaSize = 0; preview.control.AnimateOpacity(0, 1, 200); #endif Parent.ResumeLayout(); preview.AsyncReportStart(); #if WPF _ = System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke( #elif AVALONIA _ = Avalonia.Threading.Dispatcher.UIThread.InvokeAsync( #else this.BeginInvoke( #endif new Action(() => { try { report.AsyncPrepareRun(); // run report pages (pseudo async way). May throw runtime exception } catch (Exception ex) { FRMessageBox.Error(ex.Message); } finally { report.AsyncPrepareFinish(); // cleanup preview.AsyncReportFinish(); finished = true; } })); // wait for form is about to close (handled in the DesignerForm.cs code) embeddedPreview = preview; embeddedPreviewCompletion = new TaskCompletionSource(); await embeddedPreviewCompletion.Task; embeddedPreview = null; embeddedPreviewCompletion = null; preview.Dispose(); // show the designer control again Parent.SuspendLayout(); foreach (Control c in Parent.Controls) { if (!c.GetType().Name.Contains("RibbonControl") || Config.UseRibbon) c.Visible = true; } #if (WPF || AVALONIA) form.ExtendedAppArea = true; #endif Parent.ResumeLayout(); } } finally { if (!finished) report.AsyncPrepareFinish(); // cleanup report.Preview = savePreview; } } // adds the Start Page tab internal void AddStartPageTab() { if (StartPage != null) return; startPage = new StartPageTab(this); AddDocument(startPage); UpdatePlugins(null); } // adds the report tab internal ReportTab CreateReportTab(Report report) { return new ReportTab(this, report); } internal void AddReportTab(ReportTab tab) { AddDocument(tab); tab.UpdateUIStyle(); tab.UpdateDpiDependencies(); ActiveReportTab = tab; } private void OnUIStateChanged() { if (UIStateChanged != null) UIStateChanged(this, EventArgs.Empty); } #endregion #region Layout private void SaveRecentFiles() { string files = ""; foreach (string s in RecentFiles) { files += s + '\r'; } designerStorage.SetStr("RecentFiles", files); } private void SaveCloudReports() { string files = ""; foreach (var pair in CloudReportDictionary) { files += pair.Key + '\n' + pair.Value + '\r'; } designerStorage.SetStr("CloudReports", files); } private void RestoreRecentFiles() { string[] files = designerStorage.GetStr("RecentFiles").Split(new char[] { '\r' }, StringSplitOptions.RemoveEmptyEntries); RecentFiles.Clear(); RecentFiles.AddRange(files); } private void RestoreCloudReports() { var files = designerStorage.GetStr("CloudReports").Split('\r'); CloudReportDictionary.Clear(); if (files.Length < 1 || files[0] == string.Empty) return; foreach (var line in files) { if (line != string.Empty) { var pair = line.Split('\n'); // filename should not be rooted if (pair.Length == 2 && !Path.IsPathRooted(pair[0])) CloudReportDictionary.Add(pair[0], pair[1]); } } } /// /// Saves config to a FastReport configuration file. /// public void SaveConfig() { SaveRecentFiles(); SaveCloudReports(); plugins.SaveState(); SaveDockState(Config.Root); } /// /// Restores config from a FastReport configuration file. /// /// /// Call this method to restore the designer's layout. You need to do this after the /// designer's control is placed on a form. /// public void RestoreConfig() { BeforeRestoreState(); RestoreRecentFiles(); RestoreCloudReports(); RestoreDockState(Config.Root); plugins.RestoreState(); AfterRestoreState(); } /// /// Refresh the designer's toolbars and toolwindows layout. /// /// /// Call this method if you use /// DesignerControl. To restore /// the layout that you've created in VS design time, you need to call this method in the form's /// Load event handler. If you don't do this, tool windows like Properties, Data, Report Tree /// will not be available. /// public void RefreshLayout() { RestoreLayout(layoutState); } internal virtual void BeforeRestoreState() { SuspendLayout(); } internal virtual void AfterRestoreState() { ResumeLayout(); } private void RestoreLayout(string value) { XmlDocument doc = new XmlDocument(); if (value == null) value = ""; int startIndex = value.IndexOf(""); if (startIndex != -1) { using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(value.Substring(startIndex)))) { doc.Load(stream); } } SuspendLayout(); RestoreDockState(doc.Root); ResumeLayout(); } /// public void BeginInit() { initFlag = true; } /// public void EndInit() { if (initFlag) { if (layoutNeeded) RestoreLayout(layoutState); initFlag = false; layoutNeeded = false; if (DesignMode) DisableFloatingBars(); } } #endregion #region Commands private void InitCommands() { fcmdNew = new NewCommand(this); fcmdNewPage = new NewPageCommand(this); fcmdNewDialog = new NewDialogCommand(this); fcmdOpen = new OpenCommand(this); fcmdOpenPage = new OpenPageCommand(this); fcmdOpenViaCloud = new OpenViaCloudCommand(this); fcmdSave = new SaveCommand(this); fcmdSaveToCloud = new SaveToCloudCommand(this); fcmdSaveAs = new SaveAsCommand(this); fcmdSaveWithRandomData = new SaveWithRandomDataCommand(this); fcmdSaveAll = new SaveAllCommand(this); fcmdClose = new CloseCommand(this); fcmdCloseAll = new CloseAllCommand(this); fcmdPreview = new PreviewCommand(this); fcmdPreviewCloud = new PreviewCloudCommand(this); fcmdPrinterSetup = new PrinterSettingsCommand(this); fcmdPageSetup = new PageSettingsCommand(this); fcmdAddData = new AddDataCommand(this); fcmdSortDataSources = new SortDataSourcesCommand(this); fcmdChooseData = new ChooseDataCommand(this); fcmdUndo = new UndoCommand(this); fcmdRedo = new RedoCommand(this); fcmdCut = new CutCommand(this); fcmdCopy = new CopyCommand(this); fcmdPaste = new PasteCommand(this); fcmdFormatPainter = new FormatPainterCommand(this); fcmdDelete = new DeleteCommand(this); copyPageCommand = new CopyPageCommand(this); fcmdDeletePage = new DeletePageCommand(this); fcmdSelectAll = new SelectAllCommand(this); fcmdGroup = new GroupCommand(this); fcmdUngroup = new UngroupCommand(this); fcmdEdit = new EditCommand(this); fcmdFind = new FindCommand(this); fcmdReplace = new ReplaceCommand(this); fcmdBringToFront = new BringToFrontCommand(this); fcmdSendToBack = new SendToBackCommand(this); fcmdInsert = new InsertCommand(this); fcmdInsertBand = new InsertBandCommand(this); fcmdRecentFiles = new RecentFilesCommand(this); fcmdSelectLanguage = new SelectLanguageCommand(this); fcmdViewStartPage = new ViewStartPageCommand(this); fcmdReportSettings = new ReportSettingsCommand(this); fcmdOptions = new OptionsCommand(this); fcmdReportStyles = new ReportStylesCommand(this); fcmdReportValidation = new ReportValidationCommand(this); fcmdHelpContents = new HelpContentsCommand(this); fcmdAccount = new AccountCommand(this); fcmdAbout = new AboutCommand(this); fcmdWelcome = new WelcomeCommand(this); fcmdPolySelectAddPoint = new PolygonSelectModeCommand(this, PolyLineObject.PolygonSelectionMode.AddToLine); fcmdPolySelectBezier = new PolygonSelectModeCommand(this, PolyLineObject.PolygonSelectionMode.AddBezier); fcmdPolySelectMove = new PolygonSelectModeCommand(this, PolyLineObject.PolygonSelectionMode.MoveAndScale); fcmdPolySelectPointer = new PolygonSelectModeCommand(this, PolyLineObject.PolygonSelectionMode.Normal); fcmdPolySelectRemovePoint = new PolygonSelectModeCommand(this, PolyLineObject.PolygonSelectionMode.Delete); } internal void InitPages(int pageNo) { ActiveReportTab.InitPages(pageNo); } /// /// Initializes the workspace after the new report is loaded. /// public void InitReport() { ActiveReportTab.InitReport(); ActiveReportTab.SetModified(); } internal void InsertObject(ObjectInfo[] infos, InsertFrom source) { ObjectCollection list = new ObjectCollection(); CancelPaste(); foreach (ObjectInfo info in infos) { Base c = Activator.CreateInstance(info.Object) as Base; LastFormatting.SetFormatting(c as ReportComponentBase); c.OnBeforeInsert(info.Flags); list.Add(c); //c.Parent = ActiveReportTab.ActivePageDesigner.GetParentForPastedObjects(); Config.DesignerSettings.OnObjectInserted(this, new ObjectInsertedEventArgs(c, source)); } ActiveReportTab.ActivePageDesigner.Paste(list, source); } internal void InsertObject(ObjectInfo info, InsertFrom source) { InsertObject(new ObjectInfo[] { info }, source); } internal void ResetObjectsToolbar(bool ignoreMultiInsert) { objectsToolbar.ClickSelectButton(ignoreMultiInsert); FormatPainter = false; } internal void Exit(object sender, EventArgs e) { Form form = FindForm(); if (form != null) form.Close(); } /// /// Tries to create a new empty report. /// /// true if report was created successfully; false if user cancels the action. public bool CreateEmptyReport() { bool result = false; if (MdiMode) { Report report = new Report(); report.Designer = this; Config.DesignerSettings.OnReportLoaded(this, new ReportLoadedEventArgs(report)); AddReportTab(CreateReportTab(report)); result = true; } else result = ActiveReportTab.EmptyReport(true); if (result) { ActiveReportTab.SetModified(); UpdatePlugins(null); } return result; } internal void ErrorMsg(string msg, string objName) { MessagesWindow.AddMessage(msg, objName); } internal void ErrorMsg(string msg, int line, int column) { MessagesWindow.AddMessage(msg, line, column); } /// /// Displays a message in the "Messages" window. /// /// Message text. public void ShowMessage(string msg) { MessagesWindow.AddMessage(msg, 1, 1); } /// /// Clears the "Messages" window. /// public void ClearMessages() { MessagesWindow.ClearMessages(); } /// /// Shows the selected object's information in the designer's statusbar. /// /// Object's location. /// Object's size. /// Textual information about the selected object. /// The location of the lower-right corner of the object's. public virtual void ShowStatus(string location, string size, string text, string locationRightBot) { } /// /// Close all opened reports, ask to save changes. /// /// true if all tabs closed succesfully. /// /// Use this method to close all opened documents and save changes when you closing the main form /// that contains the designer control. To do this, create an event handler for your form's FormClosing /// event and call this method inside the handler. If it returns false, set e.Cancel to true. /// public bool CloseAll() { // close all tabs from the last tab to first. while (Documents.Count > 0) { DocumentWindow c = Documents[Documents.Count - 1]; if (!CloseDocument(c)) { // tab cannot be closed. Activate it and exit. Do not allow to close the designer. c.Activate(); return false; } } return true; } #endregion /// /// Initializes a new instance of the class with default settings. /// public Designer() { Report.EnsureInit(); plugins = new PluginCollection(this); recentFiles = new List(); clipboard = new DesignerClipboard(this); documents = new List(); objects = new ObjectCollection(); selectedObjects = new SelectedObjectCollection(); previouslySelectedObjects = new SelectedObjectCollection(); selectedComponents = new SelectedComponents(this); selectedReportComponents = new SelectedReportComponents(this); selectedTextObjects = new SelectedTextObjects(this); restrictions = Config.DesignerSettings.Restrictions.Clone(); askSave = true; lastFormatting = new LastFormatting(); designerStorage = new StorageService("Designer"); InitCommands(); InitPluginsInternal(); UpdatePlugins(null); UpdateMdiMode(); UIStyle = Config.UIStyle; SetupAutoSave(); InitRightToLeft(); UpdateDpiDependencies(null); } } }