using System;
using System.ComponentModel;
using System.IO;
using FastReport.Utils;
using FastReport.Data;
using System.Drawing.Design;
using System.Text.RegularExpressions;
namespace FastReport
{
///
/// Specifies the hyperlink type.
///
public enum HyperlinkKind
{
///
/// Specifies the hyperlink to external URL such as "http://www.fast-report.com", "mailto:"
/// or any other system command.
///
URL,
///
/// Specifies hyperlink to a given page number.
///
PageNumber,
///
/// Specifies hyperlink to a bookmark.
///
Bookmark,
///
/// Specifies hyperlink to external report. This report will be run when you follow the hyperlink.
///
DetailReport,
///
/// Specifies hyperlink to this report's page. The page will be run when you follow the hyperlink.
///
DetailPage,
///
/// Specifies a custom hyperlink. No actions performed when you click it, you should handle it
/// in the object's Click event handler.
///
Custom
}
///
/// This class contains a hyperlink settings.
///
[TypeConverter(typeof(FastReport.TypeConverters.FRExpandableObjectConverter))]
public class Hyperlink
{
#region Fields
private ReportComponentBase parent;
private HyperlinkKind kind;
private string expression;
private string value;
private string detailReportName;
private string detailPageName;
private string reportParameter;
private string valuesSeparator;
private string saveValue;
private bool openLinkInNewTab;
#endregion
#region Properties
///
/// Gets or sets the kind of hyperlink.
///
///
/// Use the Kind property to define hyperlink's behavior.
/// The hyperlink may be used to navigate to the external url, the page number,
/// the bookmark defined by other report object, the external report, the other page of this report,
/// and custom hyperlink.
///
[DefaultValue(HyperlinkKind.URL)]
public HyperlinkKind Kind
{
get { return kind; }
set { kind = value; }
}
///
/// Gets or sets the expression which value will be used for navigation.
///
///
/// Normally you should set the Expression property to
/// any valid expression that will be calculated when this object is about to print.
/// The value of an expression will be used for navigation.
/// If you want to navigate to some fixed data (URL or page number, for example),
/// use the property instead.
///
[Editor("FastReport.TypeEditors.HyperlinkExpressionEditor, FastReport", typeof(UITypeEditor))]
public string Expression
{
get { return expression; }
set { expression = value; }
}
///
/// Gets or sets a value that will be used for navigation.
///
///
/// Use this property to specify the fixed data (such as URL, page number etc). If you want to
/// navigate to some dynamically calculated value, use the property instead.
///
public string Value
{
get { return value; }
set
{
if (!Regex.IsMatch(value, "(javascript)|(<\\s*script\\s*>)", RegexOptions.IgnoreCase))
{
this.value = value;
}
else
{
this.value = "";
}
}
}
///
/// Gets or sets a value that indicate should be links open in new tab or not.
///
///
/// It works for HTML-export only!
///
public bool OpenLinkInNewTab
{
get { return openLinkInNewTab; }
set { openLinkInNewTab = value; }
}
///
/// Gets or sets an external report file name.
///
///
/// Use this property if is set to DetailReport.
/// When you follow the hyperlink, this report will be loaded and run.
/// You also may specify the report's parameter in the property.
///
[Editor("FastReport.TypeEditors.HyperlinkReportFileEditor, FastReport", typeof(UITypeEditor))]
public string DetailReportName
{
get { return detailReportName; }
set { detailReportName = value; }
}
///
/// Gets or sets the name of this report's page.
///
///
/// Use this property if is set to DetailPage.
/// When you follow the hyperlink, the specified page will be executed. It may contain the
/// detailed report. You also may specify the report's parameter in the
/// property.
///
[Editor("FastReport.TypeEditors.HyperlinkReportPageEditor, FastReport", typeof(UITypeEditor))]
public string DetailPageName
{
get { return detailPageName; }
set { detailPageName = value; }
}
///
/// Gets or sets a parameter's name that will be set to hyperlink's value.
///
///
/// Use this property if is set to DetailReport or DetailPage.
/// If you want to pass the hyperlink's value to the report's parameter, specify the
/// parameter name in this property. This parameter will be set to the hyperlink's value
/// before running a report. It may be used to display detailed information about clicked item.
/// It is also possible to pass multiple values to several parameters. If hyperlink's value
/// contains separators (the separator string can be set in the
/// property), it will be splitted to several values. That values will be passed to nested parameters
/// of the ReportParameter (you should create nested parameters by youself). For example, you have
/// the ReportParameter called "SelectedValue" which has two nested parameters: the first one is
/// "Employee" and the second is "Category". The hyperlink's value is "Andrew Fuller;Beverages".
/// It will be splitted to two values: "Andrew Fuller" and "Beverages". The first nested parameter
/// of the ReportParameter that is "Employee" in our case will be set to "Andrew Fuller";
/// the second nested parameter ("Category") will be set to "Beverages".
/// Note: when you create a parameter in the detailed report, don't forget to set
/// its DataType property. It is used to convert string values to actual data type.
///
///
[Editor("FastReport.TypeEditors.HyperlinkReportParameterEditor, FastReport", typeof(UITypeEditor))]
public string ReportParameter
{
get { return reportParameter; }
set { reportParameter = value; }
}
///
/// Gets or sets a string that will be used as a separator to pass several values
/// to the external report parameters.
///
public string ValuesSeparator
{
get { return valuesSeparator; }
set { valuesSeparator = value; }
}
internal ReportComponentBase Parent
{
get { return parent; }
}
internal Report Report
{
get { return parent.Report; }
}
#endregion
#region Private Methods
private bool ShouldSerializeValuesSeparator()
{
return ValuesSeparator != ";";
}
#endregion
#region Public Methods
///
/// Assigns values from another source.
///
/// Source to assign from.
public void Assign(Hyperlink source)
{
Kind = source.Kind;
Expression = source.Expression;
Value = source.Value;
DetailReportName = source.DetailReportName;
ReportParameter = source.ReportParameter;
DetailPageName = source.DetailPageName;
OpenLinkInNewTab = source.openLinkInNewTab;
}
internal bool Equals(Hyperlink h)
{
return h != null && Kind == h.Kind && Expression == h.Expression &&
DetailReportName == h.DetailReportName && ReportParameter == h.ReportParameter &&
DetailPageName == h.DetailPageName;
}
internal void SetParent(ReportComponentBase parent)
{
this.parent = parent;
}
internal void Calculate()
{
if (!String.IsNullOrEmpty(Expression))
{
object value = Report.Calc(Expression);
Value = value == null ? "" : value.ToString();
}
}
internal Report GetReport(bool updateParameter)
{
Report report = Report.FromFile(DetailReportName);
Report.Dictionary.ReRegisterData(report.Dictionary);
if (updateParameter)
SetParameters(report);
return report;
}
internal void SetParameters(Report report)
{
if (!String.IsNullOrEmpty(ReportParameter))
{
Parameter param = report.GetParameter(ReportParameter);
if (param != null)
{
if (Value.IndexOf(ValuesSeparator) != -1)
{
string[] values = Value.Split(new string[] { ValuesSeparator }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < values.Length; i++)
{
if (i < param.Parameters.Count)
param.Parameters[i].AsString = values[i];
}
}
else
{
param.AsString = Value;
}
}
}
}
internal void Serialize(FRWriter writer, Hyperlink hyperlink)
{
if (Kind != hyperlink.Kind)
writer.WriteValue("Hyperlink.Kind", Kind);
if (Expression != hyperlink.Expression)
writer.WriteStr("Hyperlink.Expression", Expression);
if (Value != hyperlink.Value)
writer.WriteStr("Hyperlink.Value", Value);
if (DetailReportName != hyperlink.DetailReportName)
{
// when saving to the report file, convert absolute path to the external report to relative path
// (based on the main report path).
string value = DetailReportName;
if (writer.SerializeTo == SerializeTo.Report && Report != null && !String.IsNullOrEmpty(Report.FileName))
value = FileUtils.GetRelativePath(DetailReportName, Path.GetDirectoryName(Report.FileName));
writer.WriteStr("Hyperlink.DetailReportName", value);
}
if (DetailPageName != hyperlink.DetailPageName)
writer.WriteStr("Hyperlink.DetailPageName", DetailPageName);
if (ReportParameter != hyperlink.ReportParameter)
writer.WriteStr("Hyperlink.ReportParameter", ReportParameter);
if (ValuesSeparator != hyperlink.ValuesSeparator)
writer.WriteStr("Hyperlink.ValuesSeparator", ValuesSeparator);
if (OpenLinkInNewTab != hyperlink.OpenLinkInNewTab)
writer.WriteBool("Hyperlink.OpenLinkInNewTab", OpenLinkInNewTab);
}
internal void OnAfterLoad()
{
// convert relative path to the external report to absolute path (based on the main report path).
if (String.IsNullOrEmpty(DetailReportName) || String.IsNullOrEmpty(Report.FileName))
return;
if (!Path.IsPathRooted(DetailReportName))
DetailReportName = Path.GetDirectoryName(Report.FileName) + Path.DirectorySeparatorChar + DetailReportName;
}
internal void SaveState()
{
saveValue = Value;
}
internal void RestoreState()
{
Value = saveValue;
}
#endregion
internal Hyperlink(ReportComponentBase parent)
{
SetParent(parent);
expression = "";
value = "";
detailReportName = "";
detailPageName = "";
reportParameter = "";
valuesSeparator = ";";
}
}
}