using FastReport.Engine;
using FastReport.Forms;
using FastReport.Preview;
using FastReport.Utils;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Printing;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FastReport
{
partial class Report
{
#region Private Fields
private int tickCount;
private EmailSettings emailSettings;
private FastReport.Preview.PreviewControl preview;
private BaseForm previewForm;
private PrintSettings printSettings;
private bool isPreviewing;
#endregion Private Fields
#region Public Properties
///
/// Gets the email settings such as recipients, subject, message body.
///
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[SRCategory("Email")]
public EmailSettings EmailSettings
{
get { return emailSettings; }
}
///
/// Gets or sets the report preview control.
///
///
/// Use this property to attach a custom preview to your report. To do this, place the PreviewControl
/// control to your form and set the report's Preview property to this control.
///
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Preview.PreviewControl Preview
{
get { return preview; }
set
{
preview = value;
if (value != null)
value.SetReport(this);
}
}
///
/// Gets the print settings such as printer name, copies, pages to print etc.
///
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[SRCategory("Print")]
public PrintSettings PrintSettings
{
get { return printSettings; }
}
///
///
///
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsPreviewing
{
get { return isPreviewing; }
}
#endregion Public Properties
#region Public Methods
///
/// Prepares the report and prints it.
///
public void Print()
{
if (Prepare())
PrintPrepared();
}
///
/// Prints the report with the "Print" dialog.
/// Report should be prepared using the method.
///
public void PrintPrepared()
{
if (PreparedPages != null)
PreparedPages.Print();
}
///
/// Prints the report without the "Print" dialog.
/// Report should be prepared using the method.
///
/// Printer-specific settings.
///
/// Use the following code if you want to show the "Print" dialog, then print:
///
/// if (report.Prepare())
/// {
/// PrinterSettings printerSettings = null;
/// if (report.ShowPrintDialog(out printerSettings))
/// {
/// report.PrintPrepared(printerSettings);
/// }
/// }
///
///
public void PrintPrepared(PrinterSettings printerSettings)
{
if (PreparedPages != null)
PreparedPages.Print(printerSettings, 1);
}
///
/// Prepares the report and shows it in the preview window.
///
public void Show()
{
Show(true, null);
}
///
/// Prepares the report and shows it in the preview window.
///
/// A value that specifies whether the preview window should be modal.
public void Show(bool modal)
{
Show(modal, null);
}
///
/// Prepares the report and shows it in the preview window.
///
/// A value that specifies whether the preview window should be modal.
/// The owner of the preview window.
public void Show(bool modal, IWin32Window owner)
{
if (Prepare())
ShowPrepared(modal, null, owner);
else if (Preview != null)
{
Preview.Clear();
Preview.Refresh();
}
}
///
/// Prepares the report and shows it in the preview window.
///
/// The main MDI form which will be a parent for the preview window.
public void Show(Form mdiParent)
{
if (Prepare())
ShowPrepared(false, mdiParent, null);
else if (Preview != null)
{
Preview.Clear();
Preview.Refresh();
}
}
///
/// Previews the report. The report should be prepared using the method.
///
public void ShowPrepared()
{
ShowPrepared(true);
}
///
/// Previews the prepared report.
///
/// A value that specifies whether the preview window should be modal.
public void ShowPrepared(bool modal)
{
ShowPrepared(modal, null, null);
}
///
/// Previews the prepared report.
///
/// A value that specifies whether the preview window should be modal.
/// The owner of the preview window.
public void ShowPrepared(bool modal, IWin32Window owner)
{
ShowPrepared(modal, null, owner);
}
///
/// Previews the prepared report.
///
/// The main MDI form which will be a parent for the preview window.
public void ShowPrepared(Form mdiParent)
{
ShowPrepared(false, mdiParent, null);
}
///
/// Shows the "Print" dialog.
///
/// Printer-specific settings.
/// true if the dialog was closed by "Print" button.
///
/// Use the following code if you want to show the "Print" dialog, then print:
///
/// if (report.Prepare())
/// {
/// PrinterSettings printerSettings = null;
/// if (report.ShowPrintDialog(out printerSettings))
/// {
/// report.PrintPrepared(printerSettings);
/// }
/// }
///
///
public bool ShowPrintDialog(out PrinterSettings printerSettings)
{
printerSettings = null;
using (PrinterSetupForm dialog = new PrinterSetupForm())
{
dialog.Report = this;
dialog.PrintDialog = true;
if (dialog.ShowDialog() != DialogResult.OK)
return false;
printerSettings = dialog.PrinterSettings;
}
return true;
}
#endregion Public Methods
#region Async Prepare/Show methods
/* proposed usage:
try
{
if (AsyncPrepareStart()) // startup, compile, run dialogs. May throw a compiler exception
AsyncPrepareRun(); // run report pages (may be run pseudo async way)
}
finally
{
AsyncPrepareFinish(); // cleanup
}
*/
internal async Task AsyncPrepareStart()
{
SetRunning(true);
ClearPreparedPages();
SetPreparedPages(new Preview.PreparedPages(this));
engine = new ReportEngine(this);
StartPerformanceCounter();
Compile();
Engine.RunPhase1();
// WPF: dialogs should be run here, before we set up modal preview window (deadlock issue)
return await Engine.RunDialogsAsync();
}
internal void AsyncPrepareRun()
{
Engine.RunPhase2(false, null);
}
internal void AsyncPrepareFinish()
{
Engine.RunFinished();
StopPerformanceCounter();
SetRunning(false);
if (Config.ReportSettings.ShowPerformance)
Preview?.ShowPerformance(String.Format(Res.Get("Messages,Performance"), tickCount));
if (ReportInfo.SavePreviewPicture && PreparedPages.Count > 0)
SavePreviewPicture();
}
///
/// Prepares the report and shows it in the provided PreviewControl (async way).
///
/// The preview control.
public async Task PrepareAsync(PreviewControl preview)
{
if (preview == null)
throw new ArgumentNullException(nameof(preview));
bool saveProgress = Config.ReportSettings.ShowProgress;
Config.ReportSettings.ShowProgress = false;
var saveButtons = preview.Buttons;
bool finished = false;
try
{
if (await AsyncPrepareStart()) // startup, compile, run dialogs. May throw a compiler exception
{
// setup preview control
preview.SetAsyncReportRunning();
preview.Buttons |= PreviewButtons.Close;
Preview = preview;
SetupPreviewControl();
preview.AsyncReportStart();
var tcs = new System.Threading.Tasks.TaskCompletionSource();
var timer = new Timer() { Interval = 50 };
timer.Tick += (s, args) =>
{
timer.Dispose();
try
{
AsyncPrepareRun(); // run report pages (pseudo async way). May throw a runtime exception
}
finally
{
AsyncPrepareFinish(); // cleanup
preview.AsyncReportFinish();
finished = true;
tcs.SetResult(true);
}
};
timer.Start();
Config.PreviewSettings.OnPreviewOpened(Preview);
// wait for report to finish
await tcs.Task;
}
}
finally
{
if (!finished)
AsyncPrepareFinish(); // cleanup
Config.ReportSettings.ShowProgress = saveProgress;
preview.Buttons = saveButtons;
}
}
private async Task ShowAsync(bool modal, Form mdiParent, IWin32Window owner)
{
bool saveProgress = Config.ReportSettings.ShowProgress;
Config.ReportSettings.ShowProgress = false;
bool finished = false;
try
{
if (await AsyncPrepareStart()) // startup, compile, run dialogs. May throw a compiler exception
{
// create preview form
previewForm = CreatePreviewForm();
previewForm.MdiParent = mdiParent;
// setup preview control
var preview = Preview;
preview.SetAsyncReportRunning();
preview.Buttons |= PreviewButtons.Close;
SetupPreviewControl();
preview.AsyncReportStart();
previewForm.Shown += (sender, e) =>
{
var timer = new Timer() { Interval = 50 };
timer.Tick += (s, args) =>
{
timer.Dispose();
try
{
AsyncPrepareRun(); // run report pages (pseudo async way). May throw a runtime exception
}
finally
{
AsyncPrepareFinish(); // cleanup
preview.AsyncReportFinish();
finished = true;
}
};
timer.Start();
};
#if AVALONIA
await ShowPreviewFormAsync(modal, mdiParent, owner);
#else
ShowPreviewForm(modal, mdiParent, owner);
#endif
}
}
finally
{
if (!finished)
AsyncPrepareFinish(); // cleanup
Config.ReportSettings.ShowProgress = saveProgress;
finished = true;
}
}
///
/// Prepares the report and shows it in the preview window (async way).
///
public async Task ShowAsync() => await ShowAsync(true, null);
///
/// Prepares the report and shows it in the preview window (async way).
///
/// A value that specifies whether the preview window should be modal.
public async Task ShowAsync(bool modal) => await ShowAsync(modal, null);
///
/// Prepares the report and shows it in the preview window (async way).
///
/// A value that specifies whether the preview window should be modal.
/// The owner of the preview window.
public async Task ShowAsync(bool modal, IWin32Window owner) => await ShowAsync(modal, null, owner);
///
/// Prepares the report and shows it in the preview window (async way).
///
/// The main MDI form which will be a parent for the preview window.
public async Task ShowAsync(Form mdiParent) => await ShowAsync(false, mdiParent, null);
#endregion
#region Private Methods
private void StartPerformanceCounter()
{
tickCount = Environment.TickCount;
}
private void StopPerformanceCounter()
{
tickCount = Environment.TickCount - tickCount;
}
private void ClearPreparedPages()
{
if (preview != null)
preview.ClearTabsExceptFirst();
else
if (preparedPages != null)
preparedPages.Clear();
}
private void DisposePreviewForm()
{
previewForm.Dispose();
previewForm = null;
preview = null;
}
private void OnClosePreview(object sender, FormClosedEventArgs e)
{
DisposePreviewForm();
}
private void SavePreviewPicture()
{
ReportPage page = PreparedPages.GetCachedPage(0);
float pageWidth = page.WidthInPixels;
float pageHeight = page.HeightInPixels;
float ratio = ReportInfo.PreviewPictureRatio;
ReportInfo.Picture = new Bitmap((int)Math.Round(pageWidth * ratio), (int)Math.Round(pageHeight * ratio));
using (Graphics g = Graphics.FromImage(ReportInfo.Picture))
{
FRPaintEventArgs args = new FRPaintEventArgs(g, ratio, ratio, GraphicCache);
page.Draw(args);
}
}
private void ShowPrepared(bool modal, Form mdiParent, IWin32Window owner)
{
// create preview form
if (Preview == null)
{
previewForm = CreatePreviewForm();
}
SetupPreviewControl();
if (Config.ReportSettings.ShowPerformance)
{
try
{
// in case the format string is wrong, use try/catch
Preview.ShowPerformance(String.Format(Res.Get("Messages,Performance"), tickCount));
}
catch
{
}
}
if (ReportInfo.SavePreviewPicture && PreparedPages.Count > 0)
SavePreviewPicture();
ShowPreviewForm(modal, mdiParent, owner);
}
private PreviewForm CreatePreviewForm()
{
var previewForm = new PreviewForm();
previewForm.ShowInTaskbar = Config.PreviewSettings.ShowInTaskbar;
if (Config.PreviewSettings.TopMost)
previewForm.TopMost = true;
previewForm.Icon = Config.PreviewSettings.Icon;
if (String.IsNullOrEmpty(Config.PreviewSettings.Text))
{
previewForm.Text = String.IsNullOrEmpty(ReportInfo.Name) ? "" : ReportInfo.Name + " - ";
previewForm.Text += Res.Get("Preview");
}
else
previewForm.Text = Config.PreviewSettings.Text;
Preview = previewForm.Preview;
Preview.UIStyle = Config.UIStyle;
Preview.FastScrolling = Config.PreviewSettings.FastScrolling;
Preview.Buttons = Config.PreviewSettings.Buttons;
Preview.SaveInitialDirectory = Config.PreviewSettings.SaveInitialDirectory;
return previewForm;
}
private void ShowPreviewForm(bool modal, Form mdiParent, IWin32Window owner)
{
Config.PreviewSettings.OnPreviewOpened(Preview);
isPreviewing = true;
if (previewForm != null && !previewForm.Visible)
{
previewForm.MdiParent = mdiParent;
if (modal)
{
previewForm.ShowDialog(owner);
DisposePreviewForm();
}
else
{
previewForm.FormClosed += new FormClosedEventHandler(OnClosePreview);
if (mdiParent == null)
previewForm.Show(owner);
else
previewForm.Show();
}
isPreviewing = false;
}
}
#if AVALONIA
private async Task ShowPreviewFormAsync(bool modal, Form mdiParent, IWin32Window owner)
{
Config.PreviewSettings.OnPreviewOpened(Preview);
isPreviewing = true;
if (previewForm != null && !previewForm.Visible)
{
previewForm.MdiParent = mdiParent;
if (modal)
{
await previewForm.ShowDialogAsync(owner);
DisposePreviewForm();
}
else
{
previewForm.FormClosed += new FormClosedEventHandler(OnClosePreview);
if (mdiParent == null)
previewForm.Show(owner);
else
previewForm.Show();
}
isPreviewing = false;
}
}
#endif
internal void SetupPreviewControl()
{
Preview.ClearTabsExceptFirst();
if (PreparedPages != null)
Preview.AddPreviewTab(this, GetReportName, null, true);
}
#endregion Private Methods
}
}