using System;
using System.Collections.Generic;
using System.Text;
using dwf.tool;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;
namespace dwf.gui
{
public class DockPageBox : UserControl
{
private PCellStyle st = new PCellStyle();
private int padding = 3;
private Orientation itemOrientation = Orientation.Horizontal;
private Orientation orientation = Orientation.Horizontal;
private DockPageList items;
private DockPage hover = null;
private DockPage closeHover = null;
private ToolTip toolTip = new ToolTip();
//private int min = 100;
private EventHandler<DockPageEventArgs> handlePageClick;
private EventHandler<DockPageEventArgs> handlePageClose;
private EventHandler<DockPageEventArgs> handlePageHover;
private EventHandler<DockPageEventArgs> handlePageLeave;
private EventHandler<DockPageEventArgs> handlePageDrag;
private EventHandler<DockPageEventArgs> handlePageMove;
private Point p0;
private bool mdown = false;
private bool visibleClose = true;
private bool visibleImage = true;
public DockPageBox()
: base()
{
items = new DockPageList(this);
items.ListChanged += ListChanged;
//toolTip.AutoPopDelay = 5000;
//toolTip.InitialDelay = 1000;
//toolTip.ReshowDelay = 1000;
//toolTip.AutomaticDelay = 1000;
DoubleBuffered = true;
st.Font = new Font("SanSeriff", 9);
st.BackBrush.Type = CellStyleBrushType.Gradient;
st.BackBrush.SColor = Color.FromArgb(220, 225, 220);
st.BackBrush.HColor = Color.FromArgb(230, 225, 200);
st.BorderBrush.SColor = Color.FromArgb(150, 150, 150);
st.BorderBrush.HColor = Color.FromArgb(150, 150, 150);
st.Round = 3;
st.Format.Trimming = StringTrimming.EllipsisCharacter;
st.FontBrush.SColor = Color.Black;
st.FontBrush.Color = Color.WhiteSmoke;
}
protected override void Dispose(bool disposing)
{
items.ListChanged -= ListChanged;
items.Dispose();
base.Dispose(disposing);
}
private void ListChanged(object sender, ListChangedEventArgs arg)
{
AllocItems(Bounds);
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
AllocItems(Bounds);
}
public void AllocItems(Rectangle allocation)
{
int max = 350;
int itemsCount = 0;
foreach (var item in this.Items)
if (item.Visible)
itemsCount++;
int childLen = GetChildsWidth(max);
if (orientation != ItemOrientation)
max = 100;
else if (orientation == Orientation.Horizontal && childLen > allocation.Width)
{
max = (allocation.Width - itemsCount * padding) / itemsCount;
foreach (var item in this.Items)
{
int w = GetToolWidth(item, max);
if (item.Visible && w < max)
{
max += (max - w) / itemsCount;
}
}
}
else if (orientation == Orientation.Vertical && childLen > allocation.Height)
{
max = (allocation.Height - itemsCount * padding) / itemsCount;
}
int x = 0;//allocation.X;
int y = 0;//allocation.Y;
foreach (DockPage w in items)
{
if (w.Visible)
{
//w.SizeRequest();
int ww = GetToolWidth(w, max);
int hh = 25;
if (orientation != ItemOrientation)
ww = max;
if (this.ItemOrientation == Orientation.Vertical)
{
hh = ww;
ww = 25;
}
w.Allocation = new Rectangle(x, y, ww < 1 ? 1 : ww, hh < 1 ? 1 : hh);
if (this.Orientation == Orientation.Horizontal)
x = w.Allocation.Right + padding;
else
y = w.Allocation.Bottom + padding;
}
}
Invalidate();
}
public event EventHandler<DockPageEventArgs> PageDrag
{
add { this.handlePageDrag += value; }
remove { this.handlePageDrag -= value; }
}
protected void OnPageDrag(DockPageEventArgs arg)
{
if (this.handlePageDrag != null)
this.handlePageDrag(this, arg);
}
public event EventHandler<DockPageEventArgs> PageMove
{
add { this.handlePageMove += value; }
remove { this.handlePageMove -= value; }
}
protected void OnPageMove(DockPageEventArgs arg)
{
if (this.handlePageMove != null)
this.handlePageMove(this, arg);
if (mdown && p0.X != 0 && p0.Y != 0)
if (Math.Abs(p0.X - arg.Point.X) > 12 ||
Math.Abs(p0.Y - arg.Point.Y) > 12)
OnPageDrag(arg);
}
public event EventHandler<DockPageEventArgs> PageClick
{
add { this.handlePageClick += value; }
remove { this.handlePageClick -= value; }
}
protected void OnPageClick(DockPageEventArgs arg)
{
if (!arg.Page.Active)
arg.Page.Active = !arg.Page.Active;
Invalidate();
if (this.handlePageClick != null)
this.handlePageClick(this, arg);
}
public event EventHandler<DockPageEventArgs> PageClose
{
add { this.handlePageClose += value; }
remove { this.handlePageClose -= value; }
}
public void ClosePage(DockPage page)
{
DockPageEventArgs arg = new DockPageEventArgs(page);
OnPageClose(arg);
}
protected void OnPageClose(DockPageEventArgs arg)
{
if (this.handlePageClose != null)
this.handlePageClose(this, arg);
if (!arg.Page.HideOnClose)
{
arg.Page.Widget.Dispose();
}
Items.Remove(arg.Page);
}
public event EventHandler<DockPageEventArgs> PageHover
{
add { this.handlePageHover += value; }
remove { this.handlePageHover -= value; }
}
protected void OnPageHover(DockPageEventArgs arg)
{
if (this.handlePageHover != null)
this.handlePageHover(this, arg);
hover = arg.Page;
toolTip.SetToolTip(this, arg.Page.Label);
}
public event EventHandler<DockPageEventArgs> PageLeave
{
add { this.handlePageLeave += value; }
remove { this.handlePageLeave -= value; }
}
protected void OnPageLeave(DockPageEventArgs arg)
{
if (this.handlePageLeave != null)
this.handlePageLeave(this, arg);
hover = null;
closeHover = null;
p0.X = 0;
}
public DockPageList Items
{
get { return this.items; }
}
public Orientation ItemOrientation
{
get { return this.itemOrientation; }
set
{
if (itemOrientation == value)
return;
itemOrientation = value;
AllocItems(Bounds);
}
}
public Orientation Orientation
{
get { return this.orientation; }
set
{
if (orientation == value)
return;
orientation = value;
AllocItems(Bounds);
}
}
public int Pad
{
get { return this.padding; }
set { padding = value; }
}
public PCellStyle PageStyle
{
get { return this.st; }
set
{
st = value;
AllocItems(Bounds);
}
}
public DockPanel Panel
{
get { return Parent as DockPanel; }
}
public DockPageEventArgs HitTest(int x, int y)
{
foreach (DockPage page in items)
{
if (page.Visible && page.Allocation.Contains(x, y))
{
DockPageEventArgs arg = new DockPageEventArgs(page);
arg.Point = new Point(x, y);
return arg;
}
}
return null;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
DockPageEventArgs arg = HitTest((int)e.X, (int)e.Y);
if (arg != null)
{
if (hover != arg.Page)
{
if (hover != null)
OnPageLeave(arg);
OnPageHover(arg);
}
else
{
OnPageMove(arg);
}
Rectangle r = GetCloseRect(arg.Page);
if (r.Contains((int)e.X, (int)e.Y))
{
closeHover = arg.Page;
Invalidate();
}
else if (closeHover != null)
{
closeHover = null;
Invalidate();
}
}
else if (hover != null)
{
OnPageLeave(new DockPageEventArgs(hover));
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
DockPageEventArgs arg = HitTest((int)e.X, (int)e.Y);
if (arg != null)
{
if (e.Button == MouseButtons.Left)
{
if (VisibleClose && GetCloseRect(arg.Page).Contains((int)e.X, (int)e.Y))
{
if (arg.Page.Widget is Form && !arg.Page.HideOnClose)
{
((Form)arg.Page.Widget).Close();
}
else
OnPageClose(arg);
}
else
{
OnPageClick(arg);
}
}
}
mdown = false;
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
DockPageEventArgs arg = HitTest((int)e.X, (int)e.Y);
if (arg != null)
{
mdown = true;
p0 = arg.Point;
}
}
protected override void OnLeave(EventArgs e)
{
base.OnLeave(e);
if (closeHover != null)
{
closeHover = null;
Invalidate();
}
if (hover != null)
OnPageLeave(new DockPageEventArgs(hover));
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
GraphContext c = new GraphContext(e.Graphics);
c.G.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
c.G.SmoothingMode = SmoothingMode.AntiAlias;
PCellStyle st = PageStyle;
Rectangle rectb = new Rectangle();
if (this.orientation == Orientation.Horizontal)
rectb = new Rectangle(0, Bounds.Bottom - 4, Bounds.Width, 4);
else
rectb = new Rectangle(Bounds.Right - 4, 0, 4, Bounds.Height);
if (Panel.PagesAlign == LayoutAlignType.Bottom)
rectb.Y = 0;
if (ItemOrientation == Orientation.Horizontal)
st.Angle = 0;
else
st.Angle = 90;
foreach (DockPage page in items)
{
if (page.Visible)
{
Rectangle rect = page.Allocation;
Rectangle irect = new Rectangle(page.Allocation.X + 2, page.Allocation.Y + 2, VisibleImage && page.Image != null ? 20 : 3, VisibleImage && page.Image != null ? 20 : 3);
Rectangle trect = new Rectangle(
page.Allocation.X + (ItemOrientation == Orientation.Horizontal ? irect.Width + 4 : 2),
page.Allocation.Y + (ItemOrientation == Orientation.Horizontal ? 2 : irect.Height + 4),
ItemOrientation == Orientation.Horizontal ? page.Allocation.Width - (2 + irect.Width + (VisibleClose ? 15 : 0)) : 20,
ItemOrientation == Orientation.Horizontal ? 18 : page.Allocation.Height - (2 + irect.Height + (VisibleClose ? 15 : 0)));
GuiService.PaintCell(c, page.Label, rect, trect, st, page.Active ? ContainsFocus ? CellDisplayState.Hover : CellDisplayState.Selected : CellDisplayState.Default);
if (VisibleClose)
PaintClose(c, page);
//image
if (VisibleImage && page.Image != null)
c.G.DrawImage(page.Image, irect);
}
}
if (items.Count > 0)
e.Graphics.FillRectangle(st.BackBrush.GetBrush(rectb, st.BackBrush.SColor), rectb);
//c.Dispose ();
}
public Rectangle GetCloseRect(DockPage page)
{
return new Rectangle(
(ItemOrientation == Orientation.Horizontal ? page.Allocation.Right - 14 : page.Allocation.X + 3),
(ItemOrientation == Orientation.Horizontal ? page.Allocation.Y + 6 : page.Allocation.Bottom - 14),
12, 12);
}
protected virtual void PaintClose(GraphContext c, DockPage page)
{
Rectangle r = GetCloseRect(page);
if (closeHover == page)
{
GraphicsPath path = GuiService.GetRoundedRect(r, 4);
c.G.DrawPath(SystemPens.ActiveBorder, path);
path.Dispose();
}
Pen p = new Pen(SystemBrushes.GrayText);
p.SetLineCap(LineCap.Round, LineCap.Round, DashCap.Round);
if (page.Active)
p.Width = 2;
else
p.Width = 1;
c.G.DrawLine(p, r.X + 3, r.Y + 3, r.Right - 3, r.Bottom - 3);
c.G.DrawLine(p, r.X + 3, r.Bottom - 3, r.Right - 3, r.Y + 3);
}
public int GetChildsWidth(int max)
{
int w = 0;
foreach (DockPage dt in items)
{
if (dt.Visible)
w += GetToolWidth(dt, max) + padding;
}
return w;
}
public int GetChildsHeight()
{
int w = 0;
foreach (DockPage dt in items)
{
w += dt.Allocation.Height;
}
return w;
}
public int GetToolWidth(DockPage tool, int max)
{
int w = 18;
if (tool.Image != null && visibleImage)
w += 20;
if (visibleClose)
w += 5;
w += (int)GuiService.MeasureString(tool.Label, st.Font, st.Format, max).Width;
return (w > max) ? max : w;
}
public bool VisibleClose
{
get { return visibleClose; }
set { visibleClose = value; }
}
public bool VisibleImage
{
get { return visibleImage; }
set { visibleImage = value; }
}
}
public class DockPageEventArgs : EventArgs
{
private DockPage page;
private Point point;
public DockPageEventArgs(DockPage page)
{
this.page = page;
}
public Point Point
{
get { return this.point; }
set { point = value; }
}
public DockPage Page
{
get { return this.page; }
set { page = value; }
}
}
}