using System; using System.ComponentModel; using System.ComponentModel.Design; using System.Windows.Forms; using System.Drawing; using System.Drawing.Drawing2D; using FastReport.Utils; #if DEBUG && !COREWIN && !(WPF || AVALONIA) using FastReport.VSDesign; #endif namespace FastReport.Controls { /// /// Represents a control that may contain several pages. It is similar to the TabControl /// but contains no tabs. This control is widely used in wizards. /// #if DEBUG && !COREWIN && !(WPF || AVALONIA) [Designer(typeof(PageControlDesigner))] #else [Designer("FastReport.VSDesign.PageControlDesigner, FastReport.VSDesign, Version=1.0.0.0, Culture=neutral, PublicKeyToken=db7e5ce63278458c, processorArchitecture=MSIL")] [ToolboxItem(false)] #endif public class PageControl : ContainerControl { #region Fields private int selectorWidth; private int selectorTabHeight; private int activePageIndex; private int highlightPageIndex; #endregion #region Properties /// /// Occurs when page is selected. /// [Category("Action")] [Description("Occurs when page is selected.")] public event EventHandler PageSelected; /// /// Gets or sets a value that determines whether the selector area is visible or not. /// [DefaultValue(false)] [Category("Appearance")] [Description("The width of selector area. Set to 0 if you don't want the selector.")] public int SelectorWidth { get { return selectorWidth; } set { selectorWidth = value; int padding = selectorWidth > 0 ? 1 : 0; if (RightToLeft == RightToLeft.Yes) Padding = new Padding(padding, padding, this.LogicalToDevice(selectorWidth), padding); else Padding = new Padding(selectorWidth, padding, padding, padding); Refresh(); } } /// /// Gets or sets the height of selector tab. /// [DefaultValue(35)] [Category("Appearance")] [Description("The height of selector tab.")] public int SelectorTabHeight { get { return selectorTabHeight; } set { selectorTabHeight = value; Refresh(); } } /// /// This property is not relevant to this class /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public new Padding Padding { get { return base.Padding; } set { base.Padding = value; } } /// /// Gets or sets the active page. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Panel ActivePage { get { if (ActivePageIndex >= 0) return Controls[ActivePageIndex] as Panel; else return null; } set { ActivePageIndex = Controls.IndexOf(value); } } /// /// Gets or sets the index of active page. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int ActivePageIndex { get { return Controls.Count == 0 ? -1 : activePageIndex; } set { if (value >= Controls.Count) value = Controls.Count - 1; if (value <= 0) value = 0; activePageIndex = value; // avoid page reordering SuspendLayout(); foreach (Control c in Controls) { c.Visible = true; } for (int i = 0; i < Controls.Count; i++) { Control c = Controls[i]; c.Visible = i == activePageIndex; if (DesignMode && c.Visible) { ISelectionService service = ((ISelectionService)GetService(typeof(ISelectionService))); if (service != null) service.SetSelectedComponents(new Control[] { c }); } } ResumeLayout(); Refresh(); OnPageSelected(); } } /// /// Gets or sets the highlighted page index. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int HighlightPageIndex { get { return highlightPageIndex; } set { if (highlightPageIndex != value) { highlightPageIndex = value; Refresh(); } } } /// /// Gets the collection of pages. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ControlCollection Pages { get { return Controls; } } #endregion #region Private Methods private void DrawTab(Graphics g, int pageIndex) { if (pageIndex == -1) return; bool active = pageIndex == ActivePageIndex; bool highlight = pageIndex == HighlightPageIndex; int left = 4; int top = 2; int width = SelectorWidth - left - 1; int height = SelectorTabHeight; top += pageIndex * height; if (active) { left -= 4; top -= 2; height += 4; width += 6; } Point[] points = new Point[] { new Point(left + width, top + height), new Point(left, top + height), new Point(left, top), new Point(left + width, top)}; Brush brush = null; if (active) brush = new SolidBrush(SystemColors.Window); else brush = new LinearGradientBrush(new Rectangle(left, top, width, height), SystemColors.Window, Color.FromArgb(240, 240, 240), 0f); g.FillPolygon(brush, points); if (active || highlight) g.FillRectangle(Brushes.Orange, left, top, 4, height); g.DrawLines(SystemPens.ControlDark, points); Font font = new Font(Font, active ? FontStyle.Bold : FontStyle.Regular); string text = Controls[pageIndex].Text; int textWidth = active ? width - 18 : width - 16; left += 12; if (RightToLeft == RightToLeft.Yes) g.ScaleTransform(-1, 1); TextFormatFlags flags = TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak; if (RightToLeft == RightToLeft.Yes) { flags |= TextFormatFlags.RightToLeft | TextFormatFlags.Right | TextFormatFlags.PreserveGraphicsTranslateTransform; left = -left - textWidth; } TextRenderer.DrawText(g, text, font, this.LogicalToDevice(new Rectangle(left, top, textWidth, height)), SystemColors.ControlText, flags); if (RightToLeft == RightToLeft.Yes) g.ScaleTransform(-1, 1); brush.Dispose(); font.Dispose(); } private void OnPageSelected() { if (PageSelected != null) PageSelected(this, EventArgs.Empty); } #endregion #region Protected Methods /// protected override void OnParentRightToLeftChanged(EventArgs e) { base.OnParentRightToLeftChanged(e); SelectorWidth = SelectorWidth; } /// protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; GraphicsState state = g.Save(); if (SelectorWidth > 0) { int sw = this.LogicalToDevice(selectorWidth); g.DrawRectangle(SystemPens.ControlDark, new Rectangle(RightToLeft == RightToLeft.Yes ? 0 : sw - 1, 0, Width - sw, Height - 1)); if (RightToLeft == RightToLeft.Yes) { g.TranslateTransform(Width, 0); g.ScaleTransform(-1, 1); } g.ScaleTransform(this.DpiMultiplier(), this.DpiMultiplier()); // draw tabs other than active for (int i = 0; i < Controls.Count; i++) { if (i != ActivePageIndex) DrawTab(g, i); } // draw active tab DrawTab(g, ActivePageIndex); } g.Restore(state); } /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); HighlightPageIndex = GetTabAt(e.Location); } /// protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); int pageIndex = GetTabAt(e.Location); if (pageIndex != -1) ActivePageIndex = pageIndex; } /// protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); HighlightPageIndex = -1; } #endregion #region Public Methods /// /// Gets tab at specified mouse point. /// /// The mouse point. /// Index of tab under mouse; -1 if mouse is outside tab area. public int GetTabAt(Point pt) { for (int i = 0; i < Controls.Count; i++) { int left = 2; int top = 2; int width = this.LogicalToDevice(SelectorWidth) - left - 1; int height = this.LogicalToDevice(SelectorTabHeight); top += i * height; if (i == ActivePageIndex) { left -= 2; top -= 2; height += 4; width += 4; } if (RightToLeft == RightToLeft.Yes) { left = Width - left - width; } if (new Rectangle(left, top, width, height).Contains(pt)) return i; } return -1; } /// /// Selects the next page. /// public void SelectNextPage() { if (ActivePageIndex < Pages.Count - 1) ActivePageIndex++; else ActivePageIndex = 0; } /// /// Selects the previous page. /// public void SelectPrevPage() { if (ActivePageIndex > 0) ActivePageIndex--; else ActivePageIndex = Pages.Count - 1; } #endregion /// /// Initializes a new instance of the class with default settings. /// public PageControl() { highlightPageIndex = -1; selectorTabHeight = 35; SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true); } } /// /// This class represents a single page of the control. /// [ToolboxItem(false)] public class PageControlPage : Panel { private Image image; /// /// Gets or sets the image associated with this page. /// public Image Image { get { return image; } set { image = value; if (Parent is PageControl) Parent.Refresh(); } } /// /// Gets or sets the page caption text. /// [Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Category("Appearance")] public override string Text { get { return base.Text; } set { base.Text = value; if (Parent is PageControl) Parent.Refresh(); } } } }