using FastReport.Cloud.StorageClient;
using FastReport.Cloud.StorageClient.Dropbox;
using FastReport.Cloud.StorageClient.FastCloud;
using FastReport.Cloud.StorageClient.Ftp;
using FastReport.Cloud.StorageClient.S3;
using FastReport.Controls;
using FastReport.Design;
using FastReport.Export;
using FastReport.Messaging;
using FastReport.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.IO;
using System.Windows.Forms;
#if !AVALONIA
using FastReport.Cloud.StorageClient.Box;
using FastReport.Cloud.StorageClient.GoogleDrive;
using FastReport.Cloud.StorageClient.SkyDrive;
using Box = FastReport.Cloud.StorageClient.Box;
using GoogleDrive = FastReport.Cloud.StorageClient.GoogleDrive;
using SkyDrive = FastReport.Cloud.StorageClient.SkyDrive;
#endif
#if !DEBUG
using FastReport.Forms;
#endif
namespace FastReport.Preview
{
///
/// Represents a Windows Forms control used to preview a report.
///
///
/// To use this control, place it on a form and link it to a report using the report's
/// property. To show a report, call
/// the Report.Show method:
///
/// report1.Preview = previewControl1;
/// report1.Show();
///
/// Use this control's methods such as , etc. to
/// handle the preview. Call method to clear the preview.
/// You can specify whether the standard toolbar is visible in the
/// property. The property allows you to hide/show the statusbar.
///
///
[ToolboxItem(true), ToolboxBitmap(typeof(Report), "Resources.PreviewControl.bmp")]
public partial class PreviewControl : UserControl
{
#region Fields
private Report report;
private List documents;
private bool toolbarVisible;
private bool statusbarVisible;
private Color pageBorderColor;
private Color activePageBorderColor;
private PreviewButtons buttons;
private PreviewExports exports;
private PreviewClouds clouds;
private float defaultZoom;
private bool locked;
private PreviewTab currentPreview;
private bool fastScrolling;
private Timer uploadTimer;
private UIStyle uiStyle;
private bool useBackColor;
private FRTabControl tabControl;
private Point pageOffset;
private string saveInitialDirectory;
private ToolStripZoomControl zoomControl;
private bool updatingZoom;
#endregion
#region Properties
///
/// Occurs when current page number is changed.
///
public event EventHandler PageChanged;
///
/// Occurs when UIStyle property is changed.
///
public event EventHandler UIStyleChanged;
///
/// Gets a reference to the report.
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Report Report
{
get { return report; }
}
///
/// Obsolete. Gets or sets the color of page border.
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
public Color PageBorderColor
{
get { return pageBorderColor; }
set { pageBorderColor = value; }
}
///
/// Gets or sets the color of active page border.
///
[DefaultValue(typeof(Color), "255, 199, 60")]
public Color ActivePageBorderColor
{
get { return activePageBorderColor; }
set { activePageBorderColor = value; }
}
///
/// Gets or sets the first page offset from the top left corner of the control.
///
public Point PageOffset
{
get { return pageOffset; }
set { pageOffset = value; }
}
///
/// Gets or sets a value indicating whether the toolbar is visible.
///
[DefaultValue(true)]
public bool ToolbarVisible
{
get { return toolbarVisible; }
set
{
toolbarVisible = value;
toolStrip.Visible = value;
}
}
///
/// Gets or sets a value indicating whether the statusbar is visible.
///
[DefaultValue(true)]
public bool StatusbarVisible
{
get { return statusbarVisible; }
set
{
statusbarVisible = value;
statusStrip.Visible = value;
}
}
///
/// Gets or sets a value indicating whether the outline control is visible.
///
[DefaultValue(false)]
public bool OutlineVisible
{
get { return outlineControl.Visible; }
set
{
splitContainer1.Panel1Collapsed = !value;
outlineControl.Visible = value;
btnOutline.Checked = value;
}
}
///
/// Specifies the set of buttons available in the toolbar.
///
[DefaultValue(PreviewButtons.All)]
public PreviewButtons Buttons
{
get { return buttons; }
set
{
buttons = value;
UpdateButtons();
}
}
///
/// Specifies the set of exports that will be available in the preview's "save" menu.
///
[DefaultValue(PreviewExports.All)]
public PreviewExports Exports
{
get { return exports; }
set
{
exports = value;
UpdateButtons();
}
}
///
/// Specifies the set of exports in clouds that will be available in the preview's "save" menu.
///
[DefaultValue(PreviewClouds.All)]
public PreviewClouds Clouds
{
get { return clouds; }
set
{
clouds = value;
UpdateButtons();
}
}
///
/// Gets or sets a value indicating whether the fast scrolling method should be used.
///
///
/// If you enable this property, the gradient background will be disabled.
///
[DefaultValue(false)]
public bool FastScrolling
{
get { return fastScrolling; }
set { fastScrolling = value; }
}
///
/// Gets or sets the visual style.
///
public UIStyle UIStyle
{
get { return uiStyle; }
set
{
uiStyle = value;
UpdateUIStyle();
UIStyleChanged?.Invoke(this, EventArgs.Empty);
}
}
///
/// Gets or sets a value indicating that the BackColor property must be used to draw the background area.
///
///
/// By default, the background area is drawn using the color defined in the current UIStyle.
///
[DefaultValue(false)]
public bool UseBackColor
{
get { return useBackColor; }
set
{
useBackColor = value;
UpdateUIStyle();
}
}
///
/// Gets the preview window's toolbar.
///
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ToolStrip ToolBar
{
get { return toolStrip; }
}
///
/// Gets the preview window's statusbar.
///
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public StatusStrip StatusBar
{
get { return statusStrip; }
}
///
/// Gets or sets the initial directory that is displayed by a save file dialog.
///
public string SaveInitialDirectory
{
get { return saveInitialDirectory; }
set { saveInitialDirectory = value; }
}
internal float DefaultZoom
{
get { return defaultZoom; }
}
internal PreviewTab CurrentPreview
{
get { return currentPreview; }
}
private bool IsPreviewEmpty
{
get { return CurrentPreview == null || CurrentPreview.Disabled; }
}
#endregion
#region Private Methods
private void CreateOpenList()
{
var openLocal = new ToolStripMenuItem(Res.Get("Preview,OpenLocal"));
openLocal.Image = this.GetImage(1);
openLocal.Font = DrawUtils.DefaultFont;
openLocal.Click += btnOpenLocal_Click;
var openViaCloud = new ToolStripMenuItem(Res.Get("Preview,OpenViaCloud"));
openViaCloud.Image = this.GetImage(261);
openViaCloud.Font = DrawUtils.DefaultFont;
openViaCloud.Click += btnOpenViaCloud_Click;
btnOpen.DropDownItems.Clear();
btnOpen.DropDownItems.AddRange(new ToolStripItem[] { openLocal, openViaCloud });
}
private void CreateSaveList()
{
var saveLocal = new ToolStripMenuItem(Res.Get("Preview,SaveLocal"));
saveLocal.Font = DrawUtils.DefaultFont;
saveLocal.Click += btnSaveLocal_Click;
var saveToCloud = new ToolStripMenuItem(Res.Get("Preview,SaveToCloud"));
saveToCloud.Image = this.GetImage(262);
saveToCloud.Font = DrawUtils.DefaultFont;
saveToCloud.Click += btnSaveToCloud_Click;
var savePrepared = new ToolStripMenuItem(Res.Get("Preview,SaveNative"));
savePrepared.Font = DrawUtils.DefaultFont;
savePrepared.DropDownItems.AddRange(new ToolStripItem[] { saveLocal, saveToCloud });
btnSave.DropDownItems.Clear();
btnSave.DropDownItems.Add(savePrepared);
CreateExportList(btnSave, Export_Click);
CreateCloudList(btnSave, SaveToCloud_Click);
//CreateMessengersList(btnSave, SendViaMessenger_Click);
}
private void CreateItems(ExportsOptions.ExportsTreeNode root, ToolStripDropDownItem button, EventHandler handler)
{
foreach (var node in root.Nodes)
{
if (node.IsCategory)
{
var categoryItem = createButtonItem(node);
CreateItems(node, categoryItem, handler);
if (categoryItem.DropDownItems.Count > 0)
button.DropDownItems.Add(categoryItem);
}
else if (node.ExportType != null)
{
bool enabled = node.Enabled;
if (node.IsExport)
{
if (Enum.TryParse(node.Tag.Object.Name, out var res))
enabled = (Exports & res) != 0;
}
else if (node.IsCloud)
{
if (Enum.TryParse(node.Name, out var res))
enabled = (Clouds & res) != 0;
}
/*else if (node.IsMessenger)
{
if (Enum.TryParse(node.Name, out var res))
enabled = (Messengers & res) != 0;
}*/
if (enabled)
{
var item = createButtonItem(node);
item.Click += handler;
button.DropDownItems.Add(item);
}
}
}
}
private ToolStripMenuItem createButtonItem(ExportsOptions.ExportsTreeNode node)
{
var item = new ToolStripMenuItem(node.ToString() + (node.IsCategory ? "" : "..."));
item.Tag = node.Tag;
item.Name = node.Name;
item.Image = node.Image ?? this.GetImage(node.ImageIndex);
item.Font = DrawUtils.DefaultFont;
return item;
}
private void CreateExportList(ToolStripDropDownItem button, EventHandler handler)
{
var options = ExportsOptions.GetInstance();
CreateItems(options.ExportsMenu, button, handler);
}
private void CreateCloudList(ToolStripDropDownItem button, EventHandler handler)
{
var options = ExportsOptions.GetInstance();
var categoryItem = createButtonItem(options.CloudMenu);
CreateItems(options.CloudMenu, categoryItem, handler);
if (categoryItem.DropDownItems.Count > 0)
{
button.DropDownItems.Add(new ToolStripSeparator());
button.DropDownItems.Add(categoryItem);
}
}
private void CreateMessengersList(ToolStripDropDownItem button, EventHandler handler)
{
var options = ExportsOptions.GetInstance();
var categoryItem = createButtonItem(options.MessengerMenu);
CreateItems(options.MessengerMenu, categoryItem, handler);
if (categoryItem.DropDownItems.Count > 0)
{
button.DropDownItems.Add(new ToolStripSeparator());
button.DropDownItems.Add(categoryItem);
}
}
private void UpdateButtons()
{
btnPrint.Available = (Buttons & PreviewButtons.Print) != 0;
btnOpen.Available = (Buttons & PreviewButtons.Open) != 0;
btnSave.Available = (Buttons & PreviewButtons.Save) != 0;
btnDesign.Available = (Buttons & PreviewButtons.Design) != 0;
btnEmail.Available = (Buttons & PreviewButtons.Email) != 0 && !Config.EmailSettings.UseMAPI;
btnFind.Available = (Buttons & PreviewButtons.Find) != 0;
btnOutline.Available = (Buttons & PreviewButtons.Outline) != 0;
btnPageSetup.Available = (Buttons & PreviewButtons.PageSetup) != 0;
btnEdit.Available = (Buttons & PreviewButtons.Edit) != 0;
btnWatermark.Available = (Buttons & PreviewButtons.Watermark) != 0;
btnFirst.Available = (Buttons & PreviewButtons.Navigator) != 0;
btnPrior.Available = (Buttons & PreviewButtons.Navigator) != 0;
tbPageNo.Available = (Buttons & PreviewButtons.Navigator) != 0;
lblTotalPages.Available = (Buttons & PreviewButtons.Navigator) != 0;
btnNext.Available = (Buttons & PreviewButtons.Navigator) != 0;
btnLast.Available = (Buttons & PreviewButtons.Navigator) != 0;
btnClose.Available = (Buttons & PreviewButtons.Close) != 0;
}
private List GetPageOfTabs()
{
List list = new List();
foreach (var tab in tabControl.Tabs)
{
if (tab is PreviewTab)
list.Add((tab as PreviewTab).PreparedPages);
}
return list;
}
private void Export_Click(object sender, EventArgs e)
{
if (IsPreviewEmpty)
return;
ObjectInfo info = (sender as ToolStripMenuItem).Tag as ObjectInfo;
if (info == null)
Save();
else
{
ExportBase export = Activator.CreateInstance(info.Object) as ExportBase;
export.CurPage = CurrentPreview.PageNo;
export.AllowSaveSettings = true;
export.ShowProgress = true;
try
{
export.Export(Report, GetPageOfTabs());
}
#if !DEBUG
catch (Exception ex)
{
using (ExceptionForm form = new ExceptionForm(ex))
{
form.ShowDialog();
}
}
#endif
finally
{
}
}
}
private async void Design()
{
if (Report == null)
return;
using (Report designedReport = new Report())
{
designedReport.FileName = Report.FileName;
if (!String.IsNullOrEmpty(Report.FileName))
designedReport.Load(designedReport.FileName);
else
using (MemoryStream repStream = new MemoryStream())
{
Report.Save(repStream);
repStream.Position = 0;
designedReport.Load(repStream);
}
Report.Dictionary.ReRegisterData(designedReport.Dictionary);
#if AVALONIA
if (await designedReport.DesignAsync())
#else
if (designedReport.Design())
#endif
{
Report.PreparedPages.Clear();
Report.PreparedPages.ClearPageCache();
try
{
Report.LoadFromString(designedReport.SaveToString());
}
catch (Exception ex)
{
FRMessageBox.Error(ex.Message);
}
if (CurrentPreview != null)
{
Report.Preview = CurrentPreview.Preview;
Report.Show();
}
}
}
}
private void SaveToCloud_Click(object sender, EventArgs e)
{
if (IsPreviewEmpty)
{
return;
}
ObjectInfo info = (sender as ToolStripMenuItem).Tag as ObjectInfo;
if (info != null)
{
CloudStorageClient client = Activator.CreateInstance(info.Object) as CloudStorageClient;
if (client is FtpStorageClient)
{
XmlItem xi = Config.Root.FindItem("FtpServer").FindItem("StorageSettings");
string server = xi.GetProp("FtpServer");
string username = xi.GetProp("FtpUsername");
FtpStorageClientForm form = new FtpStorageClientForm(server, username, "", Report);
form.ShowDialog();
}
else if (client is DropboxStorageClient)
{
XmlItem xi = Config.Root.FindItem("DropboxCloud").FindItem("StorageSettings");
string accessToken = xi.GetProp("AccessToken");
if (String.IsNullOrEmpty(accessToken))
{
ApplicationInfoForm appInfoDialog = new ApplicationInfoForm();
appInfoDialog.ShowDialog();
accessToken = appInfoDialog.AccessToken;
}
DropboxStorageClientForm form = new DropboxStorageClientForm(accessToken, Report);
form.ShowDialog();
}
else if (client is FastCloudStorageClient)
{
FastCloudStorageClientSimpleForm form = new FastCloudStorageClientSimpleForm(Report);
form.ShowDialog();
}
#if !AVALONIA
else if (client is BoxStorageClient)
{
XmlItem xi = Config.Root.FindItem("BoxCloud").FindItem("StorageSettings");
string id = xi.GetProp("ClientId");
string secret = xi.GetProp("ClientSecret");
DialogResult clientInfoDialogDialogResult = DialogResult.OK;
if (String.IsNullOrEmpty(id) || String.IsNullOrEmpty(secret))
{
Box.ClientInfoForm clientInfoDialog = new Box.ClientInfoForm();
clientInfoDialog.ShowDialog();
id = clientInfoDialog.Id;
secret = clientInfoDialog.Secret;
clientInfoDialogDialogResult = clientInfoDialog.DialogResult;
}
if (clientInfoDialogDialogResult == DialogResult.OK)
{
BoxStorageClientForm form = new BoxStorageClientForm(new SkyDrive.ClientInfo("", id, secret), Report);
form.ShowDialog();
}
}
else if (client is GoogleDriveStorageClient)
{
XmlItem xi = Config.Root.FindItem("GoogleDriveCloud").FindItem("StorageSettings");
string id = xi.GetProp("ClientId");
string secret = xi.GetProp("ClientSecret");
if (String.IsNullOrEmpty(id) || String.IsNullOrEmpty(secret))
{
GoogleDrive.ClientInfoForm clientInfoDialog = new GoogleDrive.ClientInfoForm();
clientInfoDialog.ShowDialog();
id = clientInfoDialog.Id;
secret = clientInfoDialog.Secret;
}
GoogleDriveStorageClientForm form = new GoogleDriveStorageClientForm(new SkyDrive.ClientInfo("", id, secret), Report);
form.ShowDialog();
}
else if (client is SkyDriveStorageClient)
{
XmlItem xi = Config.Root.FindItem("SkyDriveCloud").FindItem("StorageSettings");
string id = xi.GetProp("ClientId");
string secret = xi.GetProp("ClientSecret");
if (String.IsNullOrEmpty(id) || String.IsNullOrEmpty(secret))
{
SkyDrive.ClientInfoForm appInfoDialog = new SkyDrive.ClientInfoForm();
appInfoDialog.ShowDialog();
id = appInfoDialog.Id;
secret = appInfoDialog.Secret;
}
SkyDriveStorageClientForm form = new SkyDriveStorageClientForm(new SkyDrive.ClientInfo("", id, secret), Report);
form.ShowDialog();
}
#endif
else if (client is S3StorageClient)
{
XmlItem xi = Config.Root.FindItem("S3").FindItem("StorageSettings");
string accessKeyId = xi.GetProp("AccessKeyId");
string secretAccessKey = xi.GetProp("SecretAccessKey");
string region = xi.GetProp("Region");
string host = xi.GetProp("Host");
Cloud.StorageClient.S3.ClientInfoForm appInfoDialog = new Cloud.StorageClient.S3.ClientInfoForm();
appInfoDialog.AccessKeyId = accessKeyId;
appInfoDialog.SecretAccessKey = secretAccessKey;
appInfoDialog.Region = region;
appInfoDialog.Host = host;
if (appInfoDialog.ShowDialog() == DialogResult.OK)
{
accessKeyId = appInfoDialog.AccessKeyId;
secretAccessKey = appInfoDialog.SecretAccessKey;
region = appInfoDialog.Region;
host = appInfoDialog.Host;
}
else
return;
S3ClientForm form = new S3ClientForm(accessKeyId, secretAccessKey, region, host, Report);
form.Client.AfterUpload += PreviewControl_AfterUpload;
form.Client.BeforeUpload += Client_BeforeUpload;
form.ShowDialog();
}
}
}
private void Client_BeforeUpload(object sender, EventArgs e)
{
ShowPerformance(Res.Get("Preview,Uploading"));
uploadTimer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
if (lblPerformance.Text.Contains("..."))
lblPerformance.Text = lblPerformance.Text.Replace("...", "");
else
lblPerformance.Text += ".";
}
private void PreviewControl_AfterUpload(object sender, EventArgs e)
{
ShowPerformance(Res.Get("Preview,UploadDone"));
}
private void tabControl1_TabClosed(object sender, EventArgs e)
{
DeleteTab(sender as PreviewTab);
}
private void tabControl1_TabChanged(object sender, EventArgs e)
{
if (locked)
return;
currentPreview = tabControl.SelectedTab as PreviewTab;
if (currentPreview != null && !currentPreview.Fake)
{
UpdateOutline();
UpdateZoom(currentPreview.Zoom);
UpdatePageNumbers(currentPreview.PageNo, currentPreview.PageCount);
}
}
private void tabControl_Resize(object sender, EventArgs e)
{
UpdateDocumentLayout();
}
private bool CanDisposeTabReport(PreviewTab tab)
{
if (tab == null || tab.Report == null)
return false;
// if the preview is owned by Report, do not dispose
if (report == tab.Report)
return false;
// check if the same Report is used in other tabs
foreach (PreviewTab t in documents)
{
if (t != tab && t.Report == tab.Report)
{
return false;
}
}
return true;
}
private void Localize()
{
MyRes res = new MyRes("Preview");
btnPrint.Text = res.Get("PrintText");
btnPrint.ToolTipText = res.Get("Print");
btnOpen.ToolTipText = res.Get("Open");
btnOpen.Text = res.Get("OpenText");
btnDesign.Text = res.Get("DesignText");
btnDesign.ToolTipText = res.Get("Design");
btnSave.ToolTipText = res.Get("Save");
btnSave.Text = res.Get("SaveText");
btnEmail.ToolTipText = res.Get("Email");
btnFind.ToolTipText = res.Get("Find");
btnOutline.ToolTipText = res.Get("Outline");
btnPageSetup.ToolTipText = res.Get("PageSetup");
btnEdit.ToolTipText = res.Get("Edit");
btnWatermark.ToolTipText = res.Get("Watermark");
btnFirst.ToolTipText = res.Get("First");
btnPrior.ToolTipText = res.Get("Prior");
btnNext.ToolTipText = res.Get("Next");
lblTotalPages.Text = String.Format(Res.Get("Misc,ofM"), 1);
btnLast.ToolTipText = res.Get("Last");
btnClose.Text = Res.Get("Buttons,Close");
}
private void Init()
{
outlineControl.SetPreview(this);
uploadTimer = new Timer();
uploadTimer.Interval = 1500;
uploadTimer.Tick += Timer_Tick;
pageBorderColor = Color.FromArgb(80, 80, 80);
activePageBorderColor = Color.FromArgb(255, 199, 60);
pageOffset = new Point(10, 10);
defaultZoom = 1;
buttons = PreviewButtons.All;
exports = Config.PreviewSettings.Exports;
clouds = Config.PreviewSettings.Clouds;
RestoreState();
UpdateButtons();
zoomControl.ZoomValue = Zoom;
}
public void RestoreState()
{
var storage = new ControlStorageService(this, "Preview");
defaultZoom = storage.GetFloat("Zoom", 1);
splitContainer1.SplitterDistance = storage.GetDip("OutlineWidth", 250, 50, 800);
}
public void SaveState()
{
Clear();
outlineControl.Hide();
var storage = new ControlStorageService(this, "Preview");
storage.SetFloat("Zoom", Zoom);
storage.SetDip("OutlineWidth", splitContainer1.SplitterDistance);
}
private void UpdateDocumentLayout()
{
foreach (PreviewTab tab in documents)
{
tab.UpdatePages();
}
}
private void UpdateUIStyle()
{
toolStrip.Renderer = statusStrip.Renderer = UIStyleUtils.GetToolStripRenderer(UIStyle);
zoomControl.UIStyle = UIStyle;
var table = UIStyleUtils.GetColorTable(UIStyle);
if (!UseBackColor)
BackColor = table.Workspace.WorkspaceBackColor;
tabControl.Style = table.Workspace;
foreach (PreviewTab tab in documents)
{
tab.Style = UIStyle;
}
}
private void UpdateOutline()
{
outlineControl.PreparedPages = currentPreview.PreparedPages;
OutlineVisible = !currentPreview.PreparedPages.Outline.IsEmpty;
}
private void AddFakeTab()
{
PreviewTab tab = new PreviewTab(this, null, "", null);
tab.Fake = true;
documents.Add(tab);
tab.AddToTabControl(tabControl);
}
private void UpdateTabsVisible()
{
tabControl.ShowTabs = documents.Count > 1 && !documents[0].Fake;
}
private PreviewTab FindTab(string text)
{
foreach (PreviewTab tab in documents)
{
if (tab.Text == text)
return tab;
}
return null;
}
private PreviewTab FindTabByHyperlinkValue(string value)
{
foreach (PreviewTab tab in documents)
{
if (tab.HyperlinkValue == value)
return tab;
}
return null;
}
#endregion
#region Public Methods
internal void SetReport(Report report)
{
this.report = report;
}
internal void UpdatePageNumbers(int pageNo, int totalPages)
{
lblStatus.Text = String.Format(Res.Get("Misc,PageNofM"), pageNo, totalPages);
tbPageNo.Text = pageNo.ToString();
lblTotalPages.Text = String.Format(Res.Get("Misc,ofM"), totalPages);
if (PageChanged != null)
PageChanged(this, EventArgs.Empty);
}
internal void UpdateZoom(float zoom)
{
updatingZoom = true;
zoomControl.ZoomValue = zoom;
updatingZoom = false;
}
internal void UpdateUrl(string url)
{
lblUrl.Text = url;
}
internal void ShowPerformance(string text)
{
uploadTimer.Stop();
lblPerformance.Text = text;
}
internal void DoClick()
{
OnClick(EventArgs.Empty);
}
// Clears all tabs except the first one. This method is used in the report.Prepare.
// It is needed to avoid flickering when using stand-alone PreviewControl.
// When report is prepared and ShowPrepared method is called, the "fake" tab will
// be replaced with the new tab.
internal void ClearTabsExceptFirst()
{
while (documents.Count > 1)
{
DeleteTab(documents[documents.Count - 1]);
}
if (documents.Count == 1)
documents[0].Fake = true;
}
internal PreviewTab AddPreviewTab(Report report, string text, Hyperlink hyperlink, bool setActive)
{
PreviewTab tab = new PreviewTab(this, report, text, hyperlink);
documents.Add(tab);
if (documents.Count == 2 && documents[0].Fake)
DeleteTab(documents[0]);
var rescale = tabControl.Dpi() / (float)tab.Dpi();
tab.AddToTabControl(tabControl);
tab.Scale(new SizeF(rescale, rescale));
tab.UnlockLayout();
UpdateTabsVisible();
tab.UpdatePages();
if (setActive)
tabControl.SelectedTab = tab;
else
tabControl.Refresh();
return tab;
}
///
/// Adds a new report tab to the preview control.
///
/// The Report object that contains the prepared report.
/// The title for the new tab.
///
/// Prepare the report using its Prepare method before you pass it to the report parameter.
///
public void AddTab(Report report, string text)
{
if (this.report == null)
SetReport(report);
AddPreviewTab(report, text, null, true);
}
///
/// Switches to the tab with specified text.
///
/// Text of the tab.
/// true if the tab with specified text exists, or false if there is no such tab.
public bool SwitchToTab(string text)
{
PreviewTab tab = FindTab(text);
if (tab != null)
{
tabControl.SelectedTab = tab;
return true;
}
return false;
}
internal bool SwitchToTab(Hyperlink hyperlink)
{
PreviewTab tab = FindTabByHyperlinkValue(hyperlink.Value);
if (tab != null)
{
tabControl.SelectedTab = tab;
return true;
}
return false;
}
///
/// Deletes the report tab with specified text.
///
/// The text of the tab.
public void DeleteTab(string text)
{
PreviewTab tab = FindTab(text);
if (tab != null)
DeleteTab(tab);
}
///
/// Checks if the tab with specified text exists.
///
/// The text of the tab.
/// true if the tab exists.
public bool TabExists(string text)
{
return FindTab(text) != null;
}
internal void DeleteTab(PreviewTab tab)
{
if (CanDisposeTabReport(tab))
tab.Report.Dispose();
documents.Remove(tab);
tabControl.Tabs.Remove(tab);
tab.Dispose();
uploadTimer.Dispose();
UpdateTabsVisible();
}
///
/// Displays the text in the status bar.
///
/// Text to display.
public void ShowStatus(string text)
{
int tick = Environment.TickCount;
if (tick - lastTick < 50 && !string.IsNullOrEmpty(text))
return;
lastTick = tick;
lblStatus.Text = text;
statusStrip.Refresh();
Application.DoEvents();
}
internal void Lock()
{
locked = true;
}
internal void Unlock()
{
locked = false;
}
///
/// Sets the focus to the preview control.
///
public new void Focus()
{
if (currentPreview != null)
currentPreview.Focus();
}
///
/// Updates the control appearance and layout on dpi change.
///
public void UpdateDpiDependencies()
{
Font = this.LogicalToDevice(DrawUtils.DefaultFont);
tabControl.Font = Font;
toolStrip.Font = Font;
statusStrip.Font = Font;
tbPageNo.Font = Font;
outlineControl.Font = Font;
outlineControl.UpdateDpiDependencies();
toolStrip.Height = this.LogicalToDevice(26);
statusStrip.Height = this.LogicalToDevice(26);
statusStrip.Padding = new Padding(6, 0, 0, 0);
tabControl.UpdateDpiDependencies();
btnPrint.Image = this.GetImage(195);
btnOpen.Image = this.GetImage(1);
btnSave.Image = this.GetImage(2);
btnDesign.Image = this.GetImage(68);
btnEmail.Image = this.GetImage(200);
btnFind.Image = this.GetImage(181);
btnOutline.Image = this.GetImage(196);
btnPageSetup.Image = this.GetImage(13);
btnEdit.Image = this.GetImage(198);
btnWatermark.Image = this.GetImage(194);
btnFirst.Image = this.GetImage(185);
btnPrior.Image = this.GetImage(186);
btnNext.Image = this.GetImage(187);
btnLast.Image = this.GetImage(188);
tbPageNo.Size = this.LogicalToDevice(new Size(40, 21));
lblStatus.Size = this.LogicalToDevice(new Size(280, 21));
zoomControl.Size = this.LogicalToDevice(new Size(280, 26));
CreateOpenList();
CreateSaveList();
UpdateDocumentLayout();
}
#endregion
#region Async Prepare
///
/// Gets the value indicating that async report is running.
///
///
/// This value can be used to abort the report when you close the form that contains the report preview control.
///
public bool IsAsyncReportRunning { get; private set; }
// we have to call this separately before AsyncReportStart to set this flag (case: clicking reports in the reports list too fast leads to NRE)
internal void SetAsyncReportRunning() => IsAsyncReportRunning = true;
internal void AsyncReportStart()
{
Report.PreparedPages.PageAdded += AsyncReportPageAdded;
// update buttons
btnClose.Text = Res.Get("Buttons,Cancel");
EnableButtons(false);
lblStatus.Text = "";
uploadTimer.Stop();
lblPerformance.Text = "";
tbPageNo.Text = "0";
}
private int lastTick;
private void AsyncReportPageAdded(object sender, EventArgs e)
{
int tick = Environment.TickCount;
if (tick - lastTick < 50 && Report.PreparedPages.Count > 100)
return;
Application.DoEvents();
if (Report.Engine.FinalPass)
{
OutlineVisible = !Report.PreparedPages.Outline.IsEmpty;
CurrentPreview.UpdatePages();
}
lastTick = Environment.TickCount;
}
internal void AsyncReportFinish()
{
IsAsyncReportRunning = false;
Report.PreparedPages.PageAdded -= AsyncReportPageAdded;
Report.PreparedPages.ClearPageCache();
UpdateOutline();
CurrentPreview.UpdatePages();
// update buttons
btnClose.Text = Res.Get("Buttons,Close");
EnableButtons(true);
}
private void EnableButtons(bool enable)
{
foreach (ToolStripItem button in ToolBar.Items)
{
if (button == btnFirst)
break;
button.Enabled = enable;
}
}
#endregion
#region Event handlers
private void btnDesign_Click(object sender, EventArgs e)
{
Design();
}
private void btnPrint_Click(object sender, EventArgs e)
{
Print();
}
private void btnOpenLocal_Click(object sender, EventArgs e)
{
Load();
}
private void btnOpenViaCloud_Click(object sender, EventArgs e)
{
var stream = CloudCommands.LoadPreviewFile();
if (stream != null)
Load(stream);
}
private void btnSaveLocal_Click(object sender, EventArgs e)
{
Save();
}
private void btnSaveToCloud_Click(object sender, EventArgs e)
{
CloudCommands.SavePreviewFile(currentPreview.Report);
}
private void btnEmail_Click(object sender, EventArgs e)
{
SendEmail();
}
private void btnFind_Click(object sender, EventArgs e)
{
Find();
}
private void btnZoom100_Click(object sender, EventArgs e)
{
Zoom = 1;
}
private void btnZoomWholePage_Click(object sender, EventArgs e)
{
ZoomWholePage();
}
private void btnZoomPageWidth_Click(object sender, EventArgs e)
{
ZoomPageWidth();
}
private void slider_ValueChanged(object sender, EventArgs e)
{
if (updatingZoom || CurrentPreview == null)
return;
Zoom = zoomControl.ZoomValue;
CurrentPreview.Focus();
}
private void btnEdit_Click(object sender, EventArgs e)
{
EditPage();
}
private void btnFirst_Click(object sender, EventArgs e)
{
First();
}
private void btnPrior_Click(object sender, EventArgs e)
{
Prior();
}
private void btnNext_Click(object sender, EventArgs e)
{
Next();
}
private void btnLast_Click(object sender, EventArgs e)
{
Last();
}
private void cbxPageNo_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
try
{
PageNo = int.Parse(tbPageNo.Text);
}
catch
{
PageNo = PageCount;
}
CurrentPreview.Focus();
}
}
private void tbPageNo_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar != '\b' && (e.KeyChar < '0' || e.KeyChar > '9'))
e.Handled = true;
}
private void btnWatermark_Click(object sender, EventArgs e)
{
EditWatermark();
}
private void btnOutline_Click(object sender, EventArgs e)
{
OutlineVisible = btnOutline.Checked;
}
private void btnPageSetup_Click(object sender, EventArgs e)
{
PageSetup();
}
private void btnClose_Click(object sender, EventArgs e)
{
if (IsAsyncReportRunning)
{
Report.Abort();
return;
}
#if WPF
System.Windows.Window.GetWindow(control)?.Close();
#elif AVALONIA
(Avalonia.Controls.TopLevel.GetTopLevel(control) as Avalonia.Controls.Window)?.Close();
#else
if (FindForm() != null)
FindForm().Close();
#endif
}
#endregion
#region Preview commands
///
/// Prints the current report.
///
/// true if report was printed; false if user cancels the "Print" dialog.
public bool Print()
{
if (CurrentPreview == null)
return false;
return CurrentPreview.Print();
}
///
/// Saves the current report to a .fpx file using the "Save FIle" dialog.
///
public void Save()
{
if (CurrentPreview == null)
return;
CurrentPreview.Save();
}
///
/// Saves the current report to a specified .fpx file.
///
public void Save(string fileName)
{
if (CurrentPreview == null)
return;
CurrentPreview.Save(fileName);
}
///
/// Saves the current report to a stream.
///
public void Save(Stream stream)
{
if (CurrentPreview == null)
return;
CurrentPreview.Save(stream);
}
private bool PreLoad()
{
if (CurrentPreview == null)
return false;
if (documents.Count == 1 && documents[0].Fake)
{
Report report = new Report();
report.SetPreparedPages(new PreparedPages(report));
AddTab(report, "");
}
return true;
}
private void PostLoad()
{
UpdateOutline();
}
///
/// Loads the report from a .fpx file using the "Open File" dialog.
///
public new void Load()
{
if (CurrentPreview == null)
return;
CurrentPreview.Load();
UpdateOutline();
}
///
/// Loads the report from a specified .fpx file.
///
public new void Load(string fileName)
{
if (CurrentPreview == null)
return;
CurrentPreview.Load(fileName);
UpdateOutline();
}
///
/// Load the report from a stream.
///
/// The stream to load from.
public new void Load(Stream stream)
{
if (CurrentPreview == null)
return;
CurrentPreview.Load(stream);
UpdateOutline();
}
///
/// Sends an email.
///
public void SendEmail()
{
if (CurrentPreview == null)
return;
CurrentPreview.SendEmail();
}
///
/// Finds the text in the current report using the "Find Text" dialog.
///
public void Find()
{
if (CurrentPreview == null)
return;
CurrentPreview.Find();
}
///
/// Finds the specified text in the current report.
///
/// Text to find.
/// A value indicating whether the search is case-sensitive.
/// A value indicating whether the search matches whole words only.
/// true if text found.
public bool Find(string text, bool matchCase, bool wholeWord)
{
if (CurrentPreview == null)
return false;
return CurrentPreview.Find(text, matchCase, wholeWord);
}
///
/// Finds the next occurence of text specified in the Find method.
///
/// true if text found.
public bool FindNext()
{
if (CurrentPreview == null)
return false;
return CurrentPreview.FindNext();
}
///
/// Navigates to the first page.
///
public void First()
{
if (CurrentPreview == null)
return;
CurrentPreview.First();
}
///
/// Navigates to the previuos page.
///
public void Prior()
{
if (CurrentPreview == null)
return;
CurrentPreview.Prior();
}
///
/// Navigates to the next page.
///
public void Next()
{
if (CurrentPreview == null)
return;
CurrentPreview.Next();
}
///
/// Navigates to the last page.
///
public void Last()
{
if (CurrentPreview == null)
return;
CurrentPreview.Last();
}
///
/// Gets or sets the current page number.
///
///
/// This value is 1-based.
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int PageNo
{
get
{
if (CurrentPreview == null)
return 1;
return CurrentPreview.PageNo;
}
set
{
if (CurrentPreview == null)
return;
CurrentPreview.PageNo = value;
}
}
///
/// Gets the pages count in the current report.
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int PageCount
{
get
{
if (CurrentPreview == null)
return 0;
return CurrentPreview.PageCount;
}
}
///
/// Gets or sets the zoom factor.
///
///
/// 1 corresponds to 100% zoom.
///
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public float Zoom
{
get
{
if (CurrentPreview == null)
return 1;
return CurrentPreview.Zoom;
}
set
{
if (CurrentPreview != null)
{
CurrentPreview.Zoom = value;
updatingZoom = true;
zoomControl.ZoomValue = value;
updatingZoom = false;
}
}
}
///
/// Zooms in.
///
public void ZoomIn()
{
if (CurrentPreview == null)
return;
CurrentPreview.ZoomIn();
}
///
/// Zooms out.
///
public void ZoomOut()
{
if (CurrentPreview == null)
return;
CurrentPreview.ZoomOut();
}
///
/// Zooms to fit the page width.
///
public void ZoomPageWidth()
{
if (CurrentPreview == null)
return;
CurrentPreview.ZoomPageWidth();
}
///
/// Zooms to fit the whole page.
///
public void ZoomWholePage()
{
if (CurrentPreview == null)
return;
CurrentPreview.ZoomWholePage();
}
///
/// Edits the current page in the designer.
///
public void EditPage()
{
if (CurrentPreview == null)
return;
CurrentPreview.EditPage();
}
///
/// Edits the watermark.
///
public void EditWatermark()
{
if (CurrentPreview == null)
return;
CurrentPreview.EditWatermark();
}
///
/// Edits the page settings.
///
public void PageSetup()
{
if (CurrentPreview == null)
return;
CurrentPreview.PageSetup();
}
///
/// Navigates to the specified position inside a specified page.
///
/// The page number (1-based).
/// The position inside a page, in pixels.
public void PositionTo(int pageNo, PointF point)
{
if (CurrentPreview == null)
return;
CurrentPreview.PositionTo(pageNo, point);
}
///
/// Clears the preview.
///
public void Clear()
{
while (documents.Count > 0)
{
DeleteTab(documents[0]);
}
lblStatus.Text = "";
tbPageNo.Text = "";
}
///
/// Refresh the report.
///
public void RefreshReport()
{
if (CurrentPreview == null)
return;
CurrentPreview.RefreshReport();
}
#endregion
///
/// Initializes a new instance of the class.
///
public PreviewControl()
{
// we need this to ensure that static constructor of the Report was called.
Report report = new Report();
report.Dispose();
documents = new List();
InitializeComponent();
tabControl = new FRTabControl();
tabControl.Parent = splitContainer1.Panel2;
tabControl.ShowCaption = false;
tabControl.TabOrientation = TabOrientation.Top;
tabControl.Dock = DockStyle.Fill;
tabControl.Name = "tabControl";
tabControl.Resize += tabControl_Resize;
tabControl.SelectedTabChanged += tabControl1_TabChanged;
tabControl.TabClosed += tabControl1_TabClosed;
zoomControl = new ToolStripZoomControl();
zoomControl.ZoomPageWidthClick += btnZoomPageWidth_Click;
zoomControl.ZoomWholePageClick += btnZoomWholePage_Click;
zoomControl.Zoom100Click += btnZoom100_Click;
zoomControl.ValueChanged += slider_ValueChanged;
statusStrip.Items.Add(zoomControl);
#if (WPF || AVALONIA)
toolStrip.BorderThickness = new Padding(0);
var shadow = toolStrip.SetShadow(DockStyle.Bottom);
UIStyleChanged += (s, e) => shadow.Color = UIStyleUtils.GetColorTable(UIStyle).ToolStripBorder;
#endif
toolbarVisible = true;
statusbarVisible = true;
OutlineVisible = false;
UIStyle = Config.UIStyle;
Localize();
Init();
AddFakeTab();
UpdateDpiDependencies();
}
}
}