using System; using System.Collections.Generic; using System.Drawing; using System.ComponentModel; using FastReport.Utils; using System.Windows.Forms; using System.Drawing.Design; namespace FastReport { /// /// The automatic shift mode. /// public enum ShiftMode { /// /// Do not shift the object. /// Never, /// /// Shift the object up or down if any object above it shrinks or grows. /// Always, /// /// Shift the object up or down if any object above it shrinks or grows. /// Objects must have overlapped x-coordinates. /// WhenOverlapped } /// /// Specifies where to print an object. /// [Flags] [TypeConverter(typeof(FastReport.TypeConverters.FlagConverter))] public enum PrintOn { /// /// Do not print the object. /// None = 0, /// /// Print the object on the first page. If this flag is not set, the object will not /// be printed on the first page. /// FirstPage = 1, /// /// Print the object on the last page. If this flag is not set, the object will not /// be printed on the last page. You should set the report's double pass option to make /// it work correctly. /// LastPage = 2, /// /// Print the object on odd pages only. /// OddPages = 4, /// /// Print the object on even pages only. /// EvenPages = 8, /// /// Print the object on band with "Repeat on Every Page" flag when that band is repeated. /// RepeatedBand = 16, /// /// Print the object if the report has single page only. /// SinglePage = 32 } /// /// Specifies the style properties to use when style is applied. /// public enum StylePriority { /// /// Use the fill property of the style. /// UseFill, /// /// Use all style properties. /// UseAll } /// /// Base class for all report objects. /// public abstract partial class ReportComponentBase : ComponentBase { #region Fields private bool exportable; private string exportableExpression; private Border border; private FillBase fill; private string bookmark; private Hyperlink hyperlink; private bool canGrow; private bool canShrink; private bool growToBottom; private ShiftMode shiftMode; private string style; private string evenStyle; private string hoverStyle; private StylePriority evenStylePriority; private bool pageBreak; private PrintOn printOn; private string beforePrintEvent; private string afterPrintEvent; private string afterDataEvent; private string clickEvent; private bool flagSimpleBorder; private bool flagUseBorder; private bool flagUseFill; private bool flagPreviewVisible; private bool flagSerializeStyle; private bool flagProvidesHyperlinkValue; private RectangleF savedBounds; private bool savedVisible; private string savedBookmark; private Border savedBorder; private FillBase savedFill; private Cursor cursor; private string mouseMoveEvent; private string mouseUpEvent; private string mouseDownEvent; private string mouseEnterEvent; private string mouseLeaveEvent; #endregion #region Properties /// /// This event occurs before the object is added to the preview pages. /// public event EventHandler BeforePrint; /// /// This event occurs after the object was added to the preview pages. /// public event EventHandler AfterPrint; /// /// This event occurs after the object was filled with data. /// public event EventHandler AfterData; /// /// This event occurs when the user clicks the object in the preview window. /// public event EventHandler Click; /// /// Gets or sets a value that determines if the object can be exported. /// [DefaultValue(true)] [Category("Behavior")] public bool Exportable { get { return exportable; } set { exportable = value; } } /// /// Gets or sets a string containing expression that determines should be object exported. /// [DefaultValue("")] [Category("Behavior")] [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))] public virtual string ExportableExpression { get { return exportableExpression; } set { exportableExpression = value; } } /// /// Gets or sets an object's border. /// [Category("Appearance")] public virtual Border Border { get { return border; } set { border = value; if (!String.IsNullOrEmpty(Style)) Style = ""; } } /// /// Gets or sets an object's fill. /// /// /// The fill can be one of the following types: , , /// , . /// To set the solid fill color, use the simpler property. /// /// This example shows how to set the new fill and change its properties: /// /// textObject1.Fill = new SolidFill(Color.Green); /// (textObject1.Fill as SolidFill).Color = Color.Red; /// /// [Category("Appearance")] [EditorAttribute("FastReport.TypeEditors.FillEditor, FastReport", typeof(UITypeEditor))] public virtual FillBase Fill { get { return fill; } set { if (value == null) throw new ArgumentNullException("Fill"); fill = value; if (!String.IsNullOrEmpty(Style)) Style = ""; } } /// /// Gets or sets the fill color in a simple manner. /// /// /// This property can be used in a report script to change the fill color of the object. It is /// equivalent to: reportComponent1.Fill = new SolidFill(color); /// [Browsable(false)] public Color FillColor { get { return Fill is SolidFill ? (Fill as SolidFill).Color : Color.Transparent; } set { Fill = new SolidFill(value); } } /// /// Gets or sets a bookmark expression. /// /// /// This property can contain any valid expression that returns a bookmark name. This can be, for example, /// a data column. To navigate to a bookmark, you have to use the property. /// [Category("Navigation")] [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))] public string Bookmark { get { return bookmark; } set { bookmark = value; } } /// /// Gets or sets a hyperlink. /// /// /// The hyperlink is used to define clickable objects in the preview. /// When you click such object, you may navigate to the external url, the page number, /// the bookmark defined by other report object, or display the external report. /// Set the Kind property of the hyperlink to select appropriate behavior. /// Usually you should set the Expression property of the hyperlink 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 /// something fixed (URL or page number, for example) you also may set the Value /// property instead of Expression. /// [Category("Navigation")] [Editor("FastReport.TypeEditors.HyperlinkEditor, FastReport", typeof(UITypeEditor))] public Hyperlink Hyperlink { get { return hyperlink; } set { hyperlink = value; } } /// /// Determines if the object can grow. /// /// /// This property is applicable to the bands or text objects that can contain several text lines. /// If the property is set to true, object will grow to display all the information that it contains. /// [DefaultValue(false)] [Category("Behavior")] public bool CanGrow { get { return canGrow; } set { canGrow = value; } } /// /// Determines if the object can shrink. /// /// /// This property is applicable to the bands or text objects that can contain several text lines. /// If the property is set to true, object can shrink to remove the unused space. /// [DefaultValue(false)] [Category("Behavior")] public bool CanShrink { get { return canShrink; } set { canShrink = value; } } /// /// Determines if the object must grow to the band's bottom side. /// /// /// If the property is set to true, object grows to the bottom side of its parent. This is useful if /// you have several objects on a band, and some of them can grow or shrink. /// [DefaultValue(false)] [Category("Behavior")] public bool GrowToBottom { get { return growToBottom; } set { growToBottom = value; } } /// /// Gets or sets a shift mode of the object. /// /// /// See enumeration for details. /// [DefaultValue(ShiftMode.Always)] [Category("Behavior")] public ShiftMode ShiftMode { get { return shiftMode; } set { shiftMode = value; } } /// /// Gets or sets the style name. /// /// /// Style is a set of common properties such as border, fill, font, text color. The Report /// has a set of styles in the property. /// [Category("Appearance")] [Editor("FastReport.TypeEditors.StyleEditor, FastReport", typeof(UITypeEditor))] public string Style { get { return style; } set { ApplyStyle(value); style = value; } } /// /// Gets or sets a style name that will be applied to even band rows. /// /// /// Style with this name must exist in the collection. /// [Category("Appearance")] [Editor("FastReport.TypeEditors.StyleEditor, FastReport", typeof(UITypeEditor))] public string EvenStyle { get { return evenStyle; } set { evenStyle = value; } } /// /// Gets or sets a style name that will be applied to this object when the mouse pointer is over it. /// /// /// Style with this name must exist in the collection. /// [Category("Appearance")] [Editor("FastReport.TypeEditors.StyleEditor, FastReport", typeof(UITypeEditor))] public string HoverStyle { get { return hoverStyle; } set { hoverStyle = value; } } /// /// Gets or sets a value that determines which properties of the even style to use. /// /// /// Usually you will need only the Fill property of the even style to be applied. If you want to /// apply all style settings, set this property to StylePriority.UseAll. /// [DefaultValue(StylePriority.UseFill)] [Category("Appearance")] public StylePriority EvenStylePriority { get { return evenStylePriority; } set { evenStylePriority = value; } } /// /// Gets or sets a value that determines whether to insert the hard page break before processing this object. /// [Browsable(false)] [DefaultValue(false)] [Category("Behavior")] public bool PageBreak { get { return pageBreak; } set { pageBreak = value; } } /// /// Gets or sets a value that determines where to print the object. /// /// /// See the enumeration for details. /// [DefaultValue(PrintOn.FirstPage | PrintOn.LastPage | PrintOn.OddPages | PrintOn.EvenPages | PrintOn.RepeatedBand | PrintOn.SinglePage)] [Category("Behavior")] [Editor("FastReport.TypeEditors.FlagsEditor, FastReport", typeof(UITypeEditor))] public PrintOn PrintOn { get { return printOn; } set { printOn = value; } } /// /// Gets or sets a script event name that will be fired before the object will be printed in the preview page. /// [Category("Build")] public string BeforePrintEvent { get { return beforePrintEvent; } set { beforePrintEvent = value; } } /// /// Gets or sets a script event name that will be fired after the object was printed in the preview page. /// [Category("Build")] public string AfterPrintEvent { get { return afterPrintEvent; } set { afterPrintEvent = value; } } /// /// Gets or sets a script event name that will be fired after the object was filled with data. /// [Category("Build")] public string AfterDataEvent { get { return afterDataEvent; } set { afterDataEvent = value; } } /// /// Gets or sets a script event name that will be fired when the user click the object in the preview window. /// [Category("Preview")] public string ClickEvent { get { return clickEvent; } set { clickEvent = value; } } /// /// Determines if the object has custom border and use only Border.Width, Border.Style and /// Border.Color properties. /// /// /// This flag is used to disable some toolbar buttons when such object is selected. Applicable to the /// ShapeObject and LineObject. /// [Browsable(false)] public bool FlagSimpleBorder { get { return flagSimpleBorder; } set { flagSimpleBorder = value; } } /// /// Determines if the object uses the Border. /// /// /// This flag is used to disable some toolbar buttons when such object is selected. /// [Browsable(false)] public bool FlagUseBorder { get { return flagUseBorder; } set { flagUseBorder = value; } } /// /// Determines if the object uses the fill. /// /// /// This flag is used to disable some toolbar buttons when such object is selected. /// [Browsable(false)] public bool FlagUseFill { get { return flagUseFill; } set { flagUseFill = value; } } /// /// Gets or sets a value indicates that object should not be added to the preview. /// [Browsable(false)] public bool FlagPreviewVisible { get { return flagPreviewVisible; } set { flagPreviewVisible = value; } } /// /// Determines if serializing the Style property is needed. /// /// /// The Style property must be serialized last. Some ancestor classes may turn off the standard Style /// serialization and serialize it by themselves. /// [Browsable(false)] public bool FlagSerializeStyle { get { return flagSerializeStyle; } set { flagSerializeStyle = value; } } /// /// Determines if an object can provide the hyperlink value automatically. /// /// /// This flag is used in complex objects such as Matrix or Chart. These objects can provide /// a hyperlink value automatically, depending on where you click. /// [Browsable(false)] public bool FlagProvidesHyperlinkValue { get { return flagProvidesHyperlinkValue; } set { flagProvidesHyperlinkValue = value; } } /// /// Gets an object's parent band. /// internal BandBase Band { get { if (this is BandBase) return this as BandBase; Base c = Parent; while (c != null) { if (c is BandBase) return c as BandBase; c = c.Parent; } return null; } } /// /// Gets an object's parent data band. /// internal DataBand DataBand { get { if (this is DataBand) return this as DataBand; Base c = Parent; while (c != null) { if (c is DataBand) return c as DataBand; c = c.Parent; } ObjectCollection pageBands = Page.AllObjects; foreach (Base c1 in pageBands) { if (c1 is DataBand) return c1 as DataBand; } return null; } } [Browsable(false)] protected internal virtual bool IsCompilationNeeded => false; /// /// Gets or sets an object's cursor shape. /// /// /// This property is used in the preview mode. /// [Category("Appearance")] public Cursor Cursor { get { return cursor; } set { cursor = value; } } /// /// Gets or sets a script event name that will be fired when the user /// moves the mouse over the object in the preview window. /// [Category("Preview")] public string MouseMoveEvent { get { return mouseMoveEvent; } set { mouseMoveEvent = value; } } /// /// Gets or sets a script event name that will be fired when the user /// releases the mouse button in the preview window. /// [Category("Preview")] public string MouseUpEvent { get { return mouseUpEvent; } set { mouseUpEvent = value; } } /// /// Gets or sets a script event name that will be fired when the user /// clicks the mouse button in the preview window. /// [Category("Preview")] public string MouseDownEvent { get { return mouseDownEvent; } set { mouseDownEvent = value; } } /// /// Gets or sets a script event name that will be fired when the /// mouse enters the object's bounds in the preview window. /// [Category("Preview")] public string MouseEnterEvent { get { return mouseEnterEvent; } set { mouseEnterEvent = value; } } /// /// Gets or sets a script event name that will be fired when the /// mouse leaves the object's bounds in the preview window. /// [Category("Preview")] public string MouseLeaveEvent { get { return mouseLeaveEvent; } set { mouseLeaveEvent = value; } } #endregion #region Public Methods /// public override void Assign(Base source) { base.Assign(source); ReportComponentBase src = source as ReportComponentBase; Exportable = src.Exportable; ExportableExpression = src.ExportableExpression; Border = src.Border.Clone(); Fill = src.Fill.Clone(); Bookmark = src.Bookmark; Hyperlink.Assign(src.Hyperlink); CanGrow = src.CanGrow; CanShrink = src.CanShrink; GrowToBottom = src.GrowToBottom; ShiftMode = src.ShiftMode; style = src.Style; EvenStyle = src.EvenStyle; HoverStyle = src.HoverStyle; EvenStylePriority = src.EvenStylePriority; PageBreak = src.PageBreak; PrintOn = src.PrintOn; BeforePrintEvent = src.BeforePrintEvent; AfterPrintEvent = src.AfterPrintEvent; AfterDataEvent = src.AfterDataEvent; ClickEvent = src.ClickEvent; Cursor = src.Cursor; MouseMoveEvent = src.MouseMoveEvent; MouseUpEvent = src.MouseUpEvent; MouseDownEvent = src.MouseDownEvent; MouseEnterEvent = src.MouseEnterEvent; MouseLeaveEvent = src.MouseLeaveEvent; } /// /// Applies the style settings. /// /// Style to apply. public virtual void ApplyStyle(Style style) { if (style.ApplyBorder) Border = style.Border.Clone(); if (style.ApplyFill) Fill = style.Fill.Clone(); } internal void ApplyStyle(string style) { if (!String.IsNullOrEmpty(style) && Report != null) { StyleCollection styles = Report.Styles; int index = styles.IndexOf(style); if (index != -1) ApplyStyle(styles[index]); } } internal void ApplyEvenStyle() { if (!String.IsNullOrEmpty(EvenStyle) && Report != null) { StyleCollection styles = Report.Styles; int index = styles.IndexOf(EvenStyle); if (index != -1) { Style style = styles[index]; if (EvenStylePriority == StylePriority.UseFill) Fill = style.Fill.Clone(); else ApplyStyle(style); } } } /// /// Saves the current style. /// public virtual void SaveStyle() { savedBorder = Border; savedFill = Fill; } /// /// Restores the current style. /// public virtual void RestoreStyle() { Border = savedBorder; Fill = savedFill; } /// /// Draws the object's background. /// /// Draw event arguments. public void DrawBackground(FRPaintEventArgs e) { if (Width < 0.01 || Height < 0.01) return; Fill.Draw(e, AbsBounds); } /// public override void Draw(FRPaintEventArgs e) { DrawBackground(e); base.Draw(e); } /// /// Determines if the object is visible on current drawing surface. /// /// Draw event arguments. public virtual bool IsVisible(FRPaintEventArgs e) { RectangleF objRect = new RectangleF(AbsLeft * e.ScaleX, AbsTop * e.ScaleY, Width * e.ScaleX + 1, Height * e.ScaleY + 1); return e.Graphics.IsVisible(objRect); } /// /// Validate this object. /// /// List of errors public virtual List Validate() { List listError = new List(); if (Height <= 0 || Width <= 0) listError.Add(new ValidationError(Name, ValidationError.ErrorLevel.Error, Res.Get("Messages,Validator,IncorrectSize"), this)); if (Name == "") listError.Add(new ValidationError(Name, ValidationError.ErrorLevel.Error, Res.Get("Messages,Validator,UnnamedObject"), this)); if (Parent is ReportComponentBase && !Validator.RectContainInOtherRect((Parent as ReportComponentBase).AbsBounds, this.AbsBounds)) listError.Add(new ValidationError(Name, ValidationError.ErrorLevel.Error, Res.Get("Messages,Validator,OutOfBounds"), this)); return listError; } /// public override void Serialize(FRWriter writer) { ReportComponentBase c = writer.DiffObject as ReportComponentBase; base.Serialize(writer); if (Exportable != c.Exportable) writer.WriteBool("Exportable", Exportable); if (ExportableExpression != c.ExportableExpression) writer.WriteStr("ExportableExpression", ExportableExpression); Border.Serialize(writer, "Border", c.Border); //if(Fill != c.Fill) Fill.Serialize(writer, "Fill", c.Fill); if (Cursor != c.Cursor && !Config.WebMode) writer.WriteValue("Cursor", Cursor); Hyperlink.Serialize(writer, c.Hyperlink); if (Bookmark != c.Bookmark) writer.WriteStr("Bookmark", Bookmark); if (writer.SerializeTo != SerializeTo.Preview) { if (CanGrow != c.CanGrow) writer.WriteBool("CanGrow", CanGrow); if (CanShrink != c.CanShrink) writer.WriteBool("CanShrink", CanShrink); if (GrowToBottom != c.GrowToBottom) writer.WriteBool("GrowToBottom", GrowToBottom); if (ShiftMode != c.ShiftMode) writer.WriteValue("ShiftMode", ShiftMode); if (FlagSerializeStyle && Style != c.Style) writer.WriteStr("Style", Style); if (EvenStyle != c.EvenStyle) writer.WriteStr("EvenStyle", EvenStyle); if (EvenStylePriority != c.EvenStylePriority) writer.WriteValue("EvenStylePriority", EvenStylePriority); if (HoverStyle != c.HoverStyle) writer.WriteStr("HoverStyle", HoverStyle); if (PageBreak != c.PageBreak) writer.WriteBool("PageBreak", PageBreak); if (PrintOn != c.PrintOn) writer.WriteValue("PrintOn", PrintOn); if (BeforePrintEvent != c.BeforePrintEvent) writer.WriteStr("BeforePrintEvent", BeforePrintEvent); if (AfterPrintEvent != c.AfterPrintEvent) writer.WriteStr("AfterPrintEvent", AfterPrintEvent); if (AfterDataEvent != c.AfterDataEvent) writer.WriteStr("AfterDataEvent", AfterDataEvent); if (ClickEvent != c.ClickEvent) writer.WriteStr("ClickEvent", ClickEvent); if (MouseMoveEvent != c.MouseMoveEvent) writer.WriteStr("MouseMoveEvent", MouseMoveEvent); if (MouseUpEvent != c.MouseUpEvent) writer.WriteStr("MouseUpEvent", MouseUpEvent); if (MouseDownEvent != c.MouseDownEvent) writer.WriteStr("MouseDownEvent", MouseDownEvent); if (MouseEnterEvent != c.MouseEnterEvent) writer.WriteStr("MouseEnterEvent", MouseEnterEvent); if (MouseLeaveEvent != c.MouseLeaveEvent) writer.WriteStr("MouseLeaveEvent", MouseLeaveEvent); } } /// /// /// /// public override void Deserialize(FRReader reader) { base.Deserialize(reader); Fill.Deserialize(reader, "Fill"); } /// /// This method fires the Click event and the script code connected to the ClickEvent. /// /// Event data. public virtual void OnClick(EventArgs e) { if (Click != null) Click(this, e); InvokeEvent(ClickEvent, e); } /// public override void OnAfterLoad() { // if hyperlink is set to external report, we need to fix relative path to report Hyperlink.OnAfterLoad(); } /// /// Checks if there are any listeners to the Click event. /// public bool HasClickListeners() { return Click != null; } #endregion #region Report Engine /// /// Resets the data from the previous report run. /// public virtual void ResetData() { } /// /// Initializes the object before running a report. /// /// /// This method is used by the report engine, do not call it directly. /// public virtual void InitializeComponent() { // update the component's style Style = Style; Fill.InitializeComponent(); } /// /// Performs a finalization after the report is finished. /// /// /// This method is used by the report engine, do not call it directly. /// public virtual void FinalizeComponent() { Fill.FinalizeComponent(); } /// /// Saves the object's state before printing it. /// /// /// This method is called by the report engine before processing the object. /// Do not call it directly. You may override it if you are developing a new FastReport component. /// In this method you should save any object properties that may be changed during the object printing. /// The standard implementation saves the object's bounds, visibility, bookmark and hyperlink. /// public virtual void SaveState() { savedBounds = Bounds; savedVisible = Visible; savedBookmark = Bookmark; savedBorder = Border; savedFill = Fill; Hyperlink.SaveState(); } /// /// Restores the object's state after printing it. /// /// /// This method is called by the report engine after processing the object. /// Do not call it directly. You may override it if you are developing a new FastReport component. /// In this method you should restore the object properties that were saved by the method. /// public virtual void RestoreState() { Bounds = savedBounds; Visible = savedVisible; Bookmark = savedBookmark; Hyperlink.RestoreState(); Border = savedBorder; Fill = savedFill; } /// /// Calculates the object's height. /// /// Actual object's height, in pixels. /// /// Applicable to objects that contain several text lines, such as TextObject. Returns the height needed /// to display all the text lines. /// public virtual float CalcHeight() { return Height; } /// /// Gets the data from a datasource that the object is connected to. /// /// /// This method is called by the report engine before processing the object. /// Do not call it directly. You may override it if you are developing a new FastReport component. /// In this method you should get the data from a datasource that the object is connected to. /// public virtual void GetData() { Hyperlink.Calculate(); if (!String.IsNullOrEmpty(Bookmark)) { object value = Report.Calc(Bookmark); Bookmark = value == null ? "" : value.ToString(); } } /// public override string[] GetExpressions() { List expressions = new List(); string[] baseExpressions = base.GetExpressions(); if (baseExpressions != null) { expressions.AddRange(baseExpressions); } if (!String.IsNullOrEmpty(Hyperlink.Expression)) expressions.Add(Hyperlink.Expression); if (!String.IsNullOrEmpty(Bookmark)) expressions.Add(Bookmark); if (!String.IsNullOrEmpty(ExportableExpression)) { string expression = Code.CodeUtils.FixExpressionWithBrackets(ExportableExpression); if (expression.ToLower() == "true" || expression.ToLower() == "false") { expression = expression.ToLower(); } expressions.Add(expression); } return expressions.ToArray(); } /// /// This method fires the BeforePrint event and the script code connected to the BeforePrintEvent. /// /// Event data. public virtual void OnBeforePrint(EventArgs e) { if (BeforePrint != null) BeforePrint(this, e); InvokeEvent(BeforePrintEvent, e); } /// /// This method fires the AfterPrint event and the script code connected to the AfterPrintEvent. /// /// Event data. public virtual void OnAfterPrint(EventArgs e) { if (AfterPrint != null) AfterPrint(this, e); InvokeEvent(AfterPrintEvent, e); } /// /// This method fires the AfterData event and the script code connected to the AfterDataEvent. /// /// Event data. public virtual void OnAfterData(EventArgs e) { if (AfterData != null) AfterData(this, e); InvokeEvent(AfterDataEvent, e); } internal void OnAfterData() { OnAfterData(EventArgs.Empty); } #endregion /// /// Initializes a new instance of the class with default settings. /// public ReportComponentBase() { border = new Border(); fill = new SolidFill(); hyperlink = new Hyperlink(this); bookmark = ""; exportable = true; exportableExpression = ""; flagUseFill = true; flagUseBorder = true; flagPreviewVisible = true; flagSerializeStyle = true; shiftMode = ShiftMode.Always; style = ""; evenStyle = ""; hoverStyle = ""; printOn = PrintOn.FirstPage | PrintOn.LastPage | PrintOn.OddPages | PrintOn.EvenPages | PrintOn.RepeatedBand | PrintOn.SinglePage; beforePrintEvent = ""; afterPrintEvent = ""; afterDataEvent = ""; clickEvent = ""; cursor = Cursors.Default; mouseMoveEvent = ""; mouseUpEvent = ""; mouseDownEvent = ""; mouseEnterEvent = ""; mouseLeaveEvent = ""; SetFlags(Flags.CanGroup, true); if (BaseName.EndsWith("Object")) BaseName = ClassName.Substring(0, ClassName.Length - 6); } } }