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();
}
}
}
}