1696 lines
66 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Windows.Forms;
using DevComponents.DotNetBar.Rendering;
namespace DevComponents.DotNetBar
{
public class RadialMenuContainer : BaseItem
{
#region Constructor
/// <summary>
/// Initializes a new instance of the RadialMenuContainer class.
/// </summary>
public RadialMenuContainer()
{
_Colors = new RadialMenuColorTable();
_Colors.PropertyChanged += new PropertyChangedEventHandler(ColorsPropertyChanged);
m_IsContainer = true;
this.AutoCollapseOnClick = false;
this.AccessibleRole = System.Windows.Forms.AccessibleRole.Grouping;
}
void ColorsPropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.Invalidate();
}
/// <summary>
/// Returns copy of the item.
/// </summary>
public override BaseItem Copy()
{
RadialMenuContainer copy = new RadialMenuContainer();
this.CopyToItem(copy);
return copy;
}
/// <summary>
/// Copies the RadialMenuItem specific properties to new instance of the item.
/// </summary>
/// <param name="copy">New ProgressBarItem instance.</param>
internal void InternalCopyToItem(RadialMenuContainer copy)
{
CopyToItem(copy);
}
/// <summary>
/// Copies the RadialMenuItem specific properties to new instance of the item.
/// </summary>
/// <param name="copy">New RadialMenuItem instance.</param>
protected override void CopyToItem(BaseItem copy)
{
base.CopyToItem(copy);
RadialMenuContainer item = copy as RadialMenuContainer;
item.BackButtonSymbol = _BackSymbol;
item.BackButtonSymbolSize = _BackSymbolSize;
item.BackButtonSymbolSet = _BackButtonSymbolSet;
item.CenterButtonDiameter = _CenterButtonDiameter;
item.Colors.Apply(_Colors);
item.Diameter = _Diameter;
item.MenuLocation = _MenuLocation;
item.MenuType = _MenuType;
item.SubMenuEdgeItemSpacing = _SubMenuEdgeItemSpacing;
item.SubMenuEdgeWidth = _SubMenuEdgeWidth;
}
protected override void Dispose(bool disposing)
{
if (_Popup != null)
{
_Popup.Dispose();
_Popup = null;
}
if (_PopupProxy != null)
{
_PopupProxy._ParentRadialMenu = null;
_PopupProxy.Dispose();
_PopupProxy = null;
}
if (_CurrentAnimation != null) _CurrentAnimation.Stop();
base.Dispose(disposing);
}
#endregion
#region Events
/// <summary>
/// Occurs after radial menu is opened.
/// </summary>
[Description("Occurs after radial menu is opened.")]
public event EventHandler Opened;
/// <summary>
/// Raises Opened event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnOpened(EventArgs e)
{
EventHandler handler = Opened;
if (handler != null)
handler(this, e);
}
/// <summary>
/// Occurs after radial menu is closed.
/// </summary>
[Description("Occurs after radial menu is closed.")]
public event EventHandler Closed;
/// <summary>
/// Raises Closed event.
/// </summary>
/// <param name="e">Provides event arguments.</param>
protected virtual void OnClosed(EventArgs e)
{
EventHandler handler = Closed;
if (handler != null)
handler(this, e);
}
#endregion
#region Implementation
private SizeF _ScaleFactor = new SizeF(1, 1);
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public SizeF ScaleFactor
{
get { return _ScaleFactor; }
set { _ScaleFactor = value; }
}
private RadialSubItemInfo[] _SubItemsInfo = null;
private bool _RecalcSizeInProgress = false;
private const int MinItemRadialAngle = 18; // Minimum space in angles that can be occupied by single item. 18 gives 20 items on radial menu.
public override void RecalcSize()
{
if (_RecalcSizeInProgress) return; // Prevent re-entrancy
_RecalcSizeInProgress = true;
try
{
DisposeSubItemsInfo();
int diameter = ActualDiameter;
m_Rect = new Rectangle(0, 0, diameter, diameter);
//this.WidthInternal = _Diameter;
//this.HeightInternal = _Diameter;
Rectangle bounds = new Rectangle(this.LeftInternal, this.TopInternal, diameter, diameter);
bounds.Width--;
bounds.Height--;
Rectangle radialMenuBounds = bounds;
Rectangle centerBounds = bounds;
int centerButtonDiameter = ActualCenterButtonDiameter;
centerBounds.Inflate(-((diameter - centerButtonDiameter) / 2 + 1), -((diameter - centerButtonDiameter) / 2 + 1));
int subMenuEdgeItemSpacing = Dpi.Width(_SubMenuEdgeItemSpacing);
if (_MenuType == eRadialMenuType.Segment)
{
int subMenuEdgeWidth = Dpi.Width(_SubMenuEdgeWidth);
bounds.Inflate(-subMenuEdgeWidth, -subMenuEdgeWidth);
bounds.Inflate(-subMenuEdgeItemSpacing, -subMenuEdgeItemSpacing);
}
SubItemsCollection displayCollection = GetDisplayCollection();
int visibleCount = GetVisibleItemsCount(displayCollection);
if (visibleCount > 0)
{
int maxItemRadialAngle = _MaxItemRadialAngle;
if (maxItemRadialAngle == 0) maxItemRadialAngle = 180;
int itemPieAngle = Math.Max(MinItemRadialAngle, Math.Min(maxItemRadialAngle, 360 / visibleCount));
if (itemPieAngle > _MaxItemPieAngle) itemPieAngle = _MaxItemPieAngle; // Single item can consume at most half of the circle
int currentAngle = -90 - itemPieAngle / 2;
_SubItemsInfo = new RadialSubItemInfo[displayCollection.Count];
for (int i = 0; i < displayCollection.Count; i++)
{
BaseItem item = displayCollection[i];
if (!item.Visible) continue;
RadialMenuItem menuItem = item as RadialMenuItem;
if (menuItem != null)
{
menuItem.RecalcSize();
GraphicsPath path = new GraphicsPath();
path.AddArc(bounds, currentAngle, itemPieAngle);
Rectangle cb = centerBounds;
cb.Inflate(4, 4);
path.AddArc(cb, currentAngle + itemPieAngle, -itemPieAngle);
path.CloseAllFigures();
menuItem.DisplayPath = path;
menuItem.OutterBounds = bounds;
menuItem.CenterBounds = centerBounds;
menuItem.ItemAngle = currentAngle;
menuItem.ItemPieAngle = itemPieAngle;
menuItem.Bounds = Rectangle.Round(path.GetBounds());
}
else
{
item.RecalcSize();
// Position item along the imaginary inner circle
Rectangle innerCircle = bounds;
innerCircle.Width -= item.WidthInternal;
innerCircle.Height -= item.HeightInternal;
if (innerCircle.Width < centerBounds.Width) innerCircle.Inflate((centerBounds.Width - innerCircle.Width) / 2, 0);
if (innerCircle.Height < centerBounds.Height) innerCircle.Inflate(0, (centerBounds.Height - innerCircle.Height) / 2);
Point p = new Point(innerCircle.X + (int)((innerCircle.Width / 2) * Math.Cos((currentAngle + itemPieAngle / 2) * (Math.PI / 180))),
innerCircle.Y + (int)((innerCircle.Height / 2) * Math.Sin((currentAngle + itemPieAngle / 2) * (Math.PI / 180))));
p.Offset(innerCircle.Width / 2, innerCircle.Height / 2);
item.TopInternal = p.Y;
item.LeftInternal = p.X;
}
if (item != null && AnyVisibleSubItems(item))
{
Rectangle outerBounds = bounds;
outerBounds.Inflate(subMenuEdgeItemSpacing, subMenuEdgeItemSpacing);
GraphicsPath subPath = new GraphicsPath();
int expandAngle = currentAngle + 1;
int expandPieAngle = itemPieAngle - 1;
subPath.AddArc(outerBounds, expandAngle, expandPieAngle);
subPath.AddArc(radialMenuBounds, expandAngle + expandPieAngle, -expandPieAngle);
subPath.CloseAllFigures();
Rectangle signPathBounds = radialMenuBounds;
signPathBounds.Inflate(-4, -4);
Point p = new Point(signPathBounds.X + (int)((signPathBounds.Width / 2) * Math.Cos((currentAngle + itemPieAngle / 2) * (Math.PI / 180))),
signPathBounds.Y + (int)((signPathBounds.Height / 2) * Math.Sin((currentAngle + itemPieAngle / 2) * (Math.PI / 180))));
p.Offset(signPathBounds.Width / 2, signPathBounds.Height / 2);
GraphicsPath signPath = UIGraphics.GetTrianglePath(new Point(-6, -6), 12, eTriangleDirection.Right);
Matrix m = new Matrix();
if (currentAngle + itemPieAngle / 2 != 0)
{
m.Rotate(currentAngle + itemPieAngle / 2);
m.Translate(p.X, p.Y, MatrixOrder.Append);
}
else
m.Translate(p.X, p.Y);
signPath.Transform(m);
_SubItemsInfo[i] = new RadialSubItemInfo(subPath, signPath, currentAngle, itemPieAngle);
}
currentAngle += itemPieAngle;
item.Displayed = true;
}
}
}
finally
{
_RecalcSizeInProgress = false;
}
base.RecalcSize();
}
private SubItemsCollection GetDisplayCollection()
{
SubItemsCollection displayCollection = this.SubItems;
BaseItem expanded = this.ExpandedItem();
if (expanded != null) displayCollection = expanded.SubItems;
return displayCollection;
}
Rectangle _InnerBounds = Rectangle.Empty;
public override void Paint(ItemPaintArgs p)
{
p.ContextData = _Colors; // Pass to the children
p.ContextData2 = _MenuType;
#if TRIAL
if (NativeFunctions.ColorExpAlt())
{
StringFormat format=new StringFormat(StringFormat.GenericDefault);
format.Alignment=StringAlignment.Center;
format.FormatFlags=format.FormatFlags & ~(format.FormatFlags & StringFormatFlags.NoWrap);
p.Graphics.DrawString("Trial period is over.",p.Font,SystemBrushes.Highlight,this.Bounds,format);
format.Dispose();
return;
}
#endif
if (_MenuType == eRadialMenuType.Circular)
{
PaintCircular(p);
return;
}
Graphics g = p.Graphics;
if (_OpenState < 100) // Open animation transform setup
{
//p.Graphics.RotateTransform(-45 * (float)(100 - _OpenState) / 100);
int openState = Math.Max(5, _OpenState);
g.ScaleTransform(((float)openState) / 100, ((float)openState) / 100, MatrixOrder.Append);
g.TranslateTransform((this.WidthInternal / 2) * (float)(100 - openState) / 100, (this.HeightInternal / 2) * (float)(100 - openState) / 100, MatrixOrder.Append);
}
bool drawBackButton = (this.ExpandedItem() != null);
RadialMenuColorTable renderTable = RadialMenuContainer.GetColorTable();
RadialMenuColorTable localTable = _Colors;
Color borderColor = ColorScheme.GetColor(0x2B579A);
Color borderInactiveColor = Color.FromArgb(128, borderColor);
Color expandSignForeground = Color.White;
Color expandMouseOverColor = Color.FromArgb(200, borderColor);
Color backColor = Color.White;
if (!localTable.RadialMenuBorder.IsEmpty)
borderColor = localTable.RadialMenuBorder;
else if (renderTable != null && !renderTable.RadialMenuBorder.IsEmpty)
borderColor = renderTable.RadialMenuBorder;
if (!localTable.RadialMenuBackground.IsEmpty)
backColor = localTable.RadialMenuBackground;
else if (renderTable != null && !renderTable.RadialMenuBackground.IsEmpty)
backColor = renderTable.RadialMenuBackground;
if (!localTable.RadialMenuInactiveBorder.IsEmpty)
borderInactiveColor = localTable.RadialMenuInactiveBorder;
else if (renderTable != null && !renderTable.RadialMenuInactiveBorder.IsEmpty)
borderInactiveColor = renderTable.RadialMenuInactiveBorder;
if (!localTable.RadialMenuExpandForeground.IsEmpty)
expandSignForeground = localTable.RadialMenuExpandForeground;
else if (renderTable != null && !renderTable.RadialMenuExpandForeground.IsEmpty)
expandSignForeground = renderTable.RadialMenuExpandForeground;
if (!localTable.RadialMenuMouseOverBorder.IsEmpty)
expandMouseOverColor = localTable.RadialMenuMouseOverBorder;
else if (renderTable != null && !renderTable.RadialMenuMouseOverBorder.IsEmpty)
expandMouseOverColor = renderTable.RadialMenuMouseOverBorder;
Brush expandSignBrush = new SolidBrush(expandSignForeground);
Brush expandMouseOverBrush = new SolidBrush(expandMouseOverColor);
Brush borderBrush = new SolidBrush(borderColor);
Rectangle radialMenuBounds = this.Bounds;
radialMenuBounds.Width--;
radialMenuBounds.Height--;
using (GraphicsPath path = new GraphicsPath())
{
Rectangle b = radialMenuBounds;
path.AddEllipse(b);
Rectangle inner = b;
int diameter = ActualDiameter;
int centerButtonDiameter = ActualCenterButtonDiameter;
inner.Inflate(-(diameter - centerButtonDiameter) / 2, -(diameter - centerButtonDiameter) / 2);
_InnerBounds = inner;
int subMenuEdgeWidth = Dpi.Width(_SubMenuEdgeWidth);
b.Inflate(-subMenuEdgeWidth, -subMenuEdgeWidth);
using (GraphicsPath clipPath = new GraphicsPath())
{
if (!drawBackButton && this.Parent == null && string.IsNullOrEmpty(_SymbolRealized) && _Image == null)
{
clipPath.AddEllipse(inner);
g.SetClip(clipPath, CombineMode.Exclude);
}
using (SolidBrush brush = new SolidBrush(backColor))
p.Graphics.FillPath(brush, path);
if (!drawBackButton)
g.ResetClip();
}
int subMenuEdgeWidthAnimated = Dpi.Width(_SubMenuEdgeWidthAnimated);
b.Inflate(-subMenuEdgeWidthAnimated, -subMenuEdgeWidthAnimated); // Used by animation to show transition from to sub-items
path.AddEllipse(b);
//p.Graphics.DrawEllipse(Pens.Red, this.Bounds);
using (Brush brush = new SolidBrush(borderInactiveColor))
{
g.FillPath(brush, path);
using (Pen pen = new Pen(borderColor, 2))
g.DrawEllipse(pen, inner);
}
if (drawBackButton)
{
Font symFont = Symbols.GetFont(_BackSymbolSize, _BackButtonSymbolSet);
Size symSize = TextDrawing.MeasureString(g, _BackSymbol, symFont);
int descent = (int)Math.Ceiling((symFont.FontFamily.GetCellDescent(symFont.Style) *
symFont.Size / symFont.FontFamily.GetEmHeight(symFont.Style)));
symSize.Height -= descent;
TextDrawing.DrawStringLegacy(g, _BackSymbol, symFont, borderColor,
new Rectangle(inner.X + (inner.Width - symSize.Width) / 2, inner.Y + (inner.Height - symSize.Height) / 2, 0, 0),
eTextFormat.Default);
}
else if (!string.IsNullOrEmpty(_SymbolRealized))
{
Font symFont = Symbols.GetFont(_SymbolSize, _SymbolSet);
if (_SymbolTextSize.IsEmpty)
{
_SymbolTextSize = TextDrawing.MeasureString(g, _SymbolRealized, symFont);
int descent = (int)Math.Ceiling((symFont.FontFamily.GetCellDescent(symFont.Style) *
symFont.Size / symFont.FontFamily.GetEmHeight(symFont.Style)));
_SymbolTextSize.Height -= descent;
}
TextDrawing.DrawStringLegacy(g, _SymbolRealized, symFont, borderColor,
new Rectangle(inner.X + (inner.Width - _SymbolTextSize.Width) / 2 + 1, inner.Y + (inner.Height - _SymbolTextSize.Height) / 2 + 1, 0, 0),
eTextFormat.Default);
}
else if (_Image != null)
{
g.DrawImage(_Image, inner.X + (inner.Width - _Image.Width) / 2, inner.Y + (inner.Height - _Image.Height) / 2);
}
}
if (_OpenState < 100) // Open animation transform setup
{
g.ResetTransform();
g.RotateTransform(-16 * (float)(100 - _OpenState) / 100);
g.ScaleTransform(((float)Math.Max(1, _OpenState)) / 100, ((float)Math.Max(1, _OpenState)) / 100, MatrixOrder.Append);
g.TranslateTransform((this.WidthInternal / 2) * (float)(100 - _OpenState) / 100, (this.HeightInternal / 2) * (float)(100 - _OpenState) / 100, MatrixOrder.Append);
}
else if (_InnerScale < 100) // For expand animation of inner content
{
int openState = _InnerScale;
g.ScaleTransform(((float)openState) / 100, ((float)openState) / 100, MatrixOrder.Append);
g.TranslateTransform((this.WidthInternal / 2) * (float)(100 - openState) / 100, (this.HeightInternal / 2) * (float)(100 - openState) / 100, MatrixOrder.Append);
}
SubItemsCollection displayCollection = GetDisplayCollection();
for (int i = 0; i < displayCollection.Count; i++)
{
BaseItem item = displayCollection[i];
if (item.Visible && item.Displayed)
{
if (p.ClipRectangle.IsEmpty || p.ClipRectangle.IntersectsWith(item.DisplayRectangle))
{
Region oldClip = g.Clip as Region;
g.SetClip(item.DisplayRectangle, CombineMode.Intersect);
if (!g.IsClipEmpty)
item.Paint(p);
g.Clip = oldClip;
if (oldClip != null) oldClip.Dispose();
}
if (_SubItemsInfo != null && _SubItemsInfo[i] != null)
{
if (_HotSubItemInfoIndex == i)
{
g.FillPath(expandMouseOverBrush, _SubItemsInfo[i].Path);
g.FillPath(expandSignBrush, _SubItemsInfo[i].SignPath);
}
else
{
g.FillPath(borderBrush, _SubItemsInfo[i].Path);
g.FillPath(expandSignBrush, _SubItemsInfo[i].SignPath);
}
}
}
}
expandSignBrush.Dispose();
expandSignBrush = null;
expandMouseOverBrush.Dispose();
expandMouseOverBrush = null;
borderBrush.Dispose();
borderBrush = null;
g.ResetTransform();
}
private void PaintCircular(ItemPaintArgs p)
{
Graphics g = p.Graphics;
Rectangle radialMenuBounds = this.Bounds;
radialMenuBounds.Width--;
radialMenuBounds.Height--;
if (_OpenState < 100) // Open animation transform setup
{
g.ResetTransform();
g.RotateTransform(-16 * (float)(100 - _OpenState) / 100);
g.ScaleTransform(((float)Math.Max(1, _OpenState)) / 100, ((float)Math.Max(1, _OpenState)) / 100, MatrixOrder.Append);
g.TranslateTransform((this.WidthInternal / 2) * (float)(100 - _OpenState) / 100, (this.HeightInternal / 2) * (float)(100 - _OpenState) / 100, MatrixOrder.Append);
}
else if (_InnerScale < 100) // For expand animation of inner content
{
int openState = _InnerScale;
g.ScaleTransform(((float)openState) / 100, ((float)openState) / 100, MatrixOrder.Append);
g.TranslateTransform((this.WidthInternal / 2) * (float)(100 - openState) / 100, (this.HeightInternal / 2) * (float)(100 - openState) / 100, MatrixOrder.Append);
}
SubItemsCollection displayCollection = GetDisplayCollection();
for (int i = 0; i < displayCollection.Count; i++)
{
BaseItem item = displayCollection[i];
if (item.Visible && item.Displayed)
{
if (p.ClipRectangle.IsEmpty || p.ClipRectangle.IntersectsWith(item.DisplayRectangle))
{
Region oldClip = g.Clip as Region;
g.SetClip(item.DisplayRectangle, CombineMode.Intersect);
if (!g.IsClipEmpty)
item.Paint(p);
g.Clip = oldClip;
if (oldClip != null) oldClip.Dispose();
}
//if (_SubItemsInfo != null && _SubItemsInfo[i] != null)
//{
// if (_HotSubItemInfoIndex == i)
// {
// g.FillPath(expandMouseOverBrush, _SubItemsInfo[i].Path);
// g.FillPath(expandSignBrush, _SubItemsInfo[i].SignPath);
// }
// else
// {
// g.FillPath(borderBrush, _SubItemsInfo[i].Path);
// g.FillPath(expandSignBrush, _SubItemsInfo[i].SignPath);
// }
//}
}
}
g.ResetTransform();
}
private bool AnyVisibleSubItems(BaseItem item)
{
if (!item.ShowSubItems) return false;
foreach (BaseItem t in item.SubItems)
{
if (t.Visible) return true;
}
return false;
}
private int GetVisibleItemsCount(SubItemsCollection displayCollection)
{
int c = 0;
foreach (BaseItem item in displayCollection)
{
if (item.Visible) c++;
}
return c;
}
private void DisposeSubItemsInfo()
{
if (_SubItemsInfo != null)
{
for (int i = 0; i < _SubItemsInfo.Length; i++)
{
if (_SubItemsInfo[i] != null) _SubItemsInfo[i].Dispose();
}
}
_SubItemsInfo = null;
}
protected internal override void OnExpandChange()
{
if (this.Expanded)
Open();
else
{
if (HotSubItem != null) HotSubItem.InternalMouseLeave();
Close();
// Collapse all sub-items
CollapseRecursively(this);
}
base.OnExpandChange();
}
private void CollapseRecursively(BaseItem item)
{
foreach (BaseItem sub in item.SubItems)
{
sub.Expanded = false;
CollapseRecursively(sub);
}
}
private int _OpenState = 0;
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)]
public int OpenState
{
get { return _OpenState; }
set
{
RadialMenuPopup popup = _Popup;
if (this.IsDisposed | popup == null || popup != null && popup.IsDisposed)
{
_OpenState = value;
return;
}
if (popup != null && popup.InvokeRequired && !popup.IsDisposed)
{
try
{
popup.Invoke(new MethodInvoker(delegate { this.OpenState = value; }));
}
catch (ObjectDisposedException)
{ }
return;
}
if (value < 0)
value = 0;
else if (value > 100)
value = 100;
if (value != _OpenState)
{
int oldValue = _OpenState;
_OpenState = value;
OnOpenStateChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when OpenState property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnOpenStateChanged(int oldValue, int newValue)
{
//Application.DoEvents();
//OnPropertyChanged(new PropertyChangedEventArgs("OpenState"));
this.Refresh();
if (newValue == 0)
{
RadialMenuPopup popup = _Popup;
_Popup = null;
if (popup != null)
{
popup.Hide();
popup.Dispose();
}
OnClosed(EventArgs.Empty);
}
else if (newValue == 100)
{
OnOpened(EventArgs.Empty);
}
}
private int _InnerScale = 100;
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)]
public int InnerScale
{
get { return _InnerScale; }
set
{
if (value > 100)
value = 100;
else if (value < 0)
value = 0;
if (_InnerScale != value)
{
_InnerScale = value;
this.Refresh();
}
}
}
//private bool _IsOpen;
//internal bool IsOpen
//{
// get { return _IsOpen; }
// set
// {
// if (_IsOpen != value)
// {
// _IsOpen = value;
// if (_IsOpen)
// Open();
// else
// Close();
// }
// }
//}
/// <summary>
/// Returns internal popup control for radial menu.
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced)]
public RadialMenuPopup Popup
{
get
{
return _Popup;
}
}
private Animation.Animation _CurrentAnimation = null;
private RadialMenuPopup _Popup = null;
private bool _IsOpening = false;
private RadialMenuPopupProxy _PopupProxy = null;
private int _DelayCount = 0;
#region Open
internal void Open()
{
if (_IsOpening) return;
if (_OpenState > 0 && _DelayCount < 2)
{
BarUtilities.InvokeDelayed(new MethodInvoker(delegate { this.Open(); }), 300);
return;
}
try
{
_DelayCount = 0;
_IsOpening = true;
this.Displayed = true;
WaitForCurrentAnimationToComplete();
if (this.Parent != null) // Hosted elsewhere other than RadialMenu
{
IOwnerMenuSupport ownerMenu = this.GetIOwnerMenuSupport();
if (ownerMenu != null)
{
if (_PopupProxy == null) _PopupProxy = new RadialMenuPopupProxy(this);
_PopupProxy.Expanded = true;
ownerMenu.RegisterPopup(_PopupProxy);
}
}
RadialMenuPopup popup = _Popup;
if (popup == null)
{
popup = new RadialMenuPopup();
popup.DisplayItem = this;
if (_Font != null)
popup.Font = _Font;
else if (_RadialMenu != null)
popup.Font = _RadialMenu.Font;
popup.CreateControl();
}
if (_MenuLocation.IsEmpty)
{
int diameter = ActualDiameter;
if (_RadialMenu != null)
{
Point p = _RadialMenu.PointToScreen(
new Point(_RadialMenu.Width / 2, _RadialMenu.Height / 2));
p.X -= diameter / 2;
p.Y -= diameter / 2;
popup.Location = p;
}
else
{
Point p = Control.MousePosition;
p.X -= diameter / 2;
p.Y -= diameter / 2;
popup.Location = p;
}
}
else
popup.Location = _MenuLocation;
popup.Visible = true;
popup.Refresh();
_Popup = popup;
Animation.AnimationInt anim = new DevComponents.DotNetBar.Animation.AnimationInt(
new Animation.AnimationRequest(this, "OpenState", 0, 100),
Animation.AnimationEasing.EaseOutCubic, 300);
anim.AutoDispose = true;
_CurrentAnimation = anim;
anim.Start();
}
finally
{
_IsOpening = false;
}
}
#endregion
private void WaitForCurrentAnimationToComplete()
{
if (_CurrentAnimation != null)
{
DateTime start = DateTime.Now;
while (!_CurrentAnimation.IsDisposed)
{
Application.DoEvents();
if (DateTime.Now.Subtract(start).TotalMilliseconds > 1000)
{
AbortCurrentAnimation();
break;
}
}
_CurrentAnimation = null;
}
}
private void AbortCurrentAnimation()
{
Animation.Animation anim = _CurrentAnimation;
_CurrentAnimation = null;
if (anim != null)
{
anim.Stop();
anim.Dispose();
}
}
protected override bool ShouldCollapseParentItem()
{
if (this.HotSubItem != null) return HotSubItem.AutoCollapseOnClick;
return base.ShouldCollapseParentItem();
}
/// <summary>
/// Closes currently open popup.
/// </summary>
internal void Close()
{
WaitForCurrentAnimationToComplete();
Animation.AnimationInt anim = new DevComponents.DotNetBar.Animation.AnimationInt(
new Animation.AnimationRequest(this, "OpenState", 100, 0),
Animation.AnimationEasing.EaseOutCubic, 300);
anim.AutoDispose = true;
anim.Start();
//_CurrentAnimation = anim;
RadialMenuPopupProxy popupProxy = _PopupProxy;
if (popupProxy != null) // Hosted elsewhere other than RadialMenu
{
IOwnerMenuSupport ownerMenu = this.GetIOwnerMenuSupport();
if (ownerMenu != null)
{
ownerMenu.UnregisterPopup(popupProxy);
popupProxy.Expanded = false;
}
}
}
protected internal IOwnerMenuSupport GetIOwnerMenuSupport()
{
return (this.GetOwner() as IOwnerMenuSupport);
}
private int _MaxItemRadialAngle = 0;
/// <summary>
/// Indicates maximum radial angle single item in menu can consume. By default this property is set to zero which indicates that
/// radial menu is equally divided between visible menu items.
/// </summary>
[DefaultValue(0), Category("Appearance"), Description("Indicates maximum radial angle single item in menu can consume. Max value is 180.")]
public int MaxItemRadialAngle
{
get { return _MaxItemRadialAngle; }
set
{
if (value < 0)
value = 0;
else if (value > 180)
value = 180;
if (value != _MaxItemRadialAngle)
{
int oldValue = _MaxItemRadialAngle;
_MaxItemRadialAngle = value;
OnMaxItemRadialAngleChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when MaxItemRadialAngle property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnMaxItemRadialAngleChanged(int oldValue, int newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("MaxItemRadialAngle"));
NeedRecalcSize = true;
this.Refresh();
}
/// <summary>
/// Returns diameter which takes in account current scaling factor.
/// </summary>
private int ActualDiameter
{
get
{
return (int)(_Diameter * _ScaleFactor.Height);
}
}
private int _Diameter = 180;
/// <summary>
/// Gets or sets radial menu diameter. Minimum value is 64.
/// </summary>
[DefaultValue(180), Category("Appearance"), Description("Radial menu diameter.")]
public int Diameter
{
get { return _Diameter; }
set
{
if (value < 64) value = 64;
if (value != _Diameter)
{
int oldValue = _Diameter;
_Diameter = value;
OnDiameterChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when Diameter property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnDiameterChanged(int oldValue, int newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("Diameter"));
NeedRecalcSize = true;
this.Refresh();
}
/// <summary>
/// Returns actual center button diameter which takes in account current scale factor.
/// </summary>
private int ActualCenterButtonDiameter
{
get
{
return (int)(_CenterButtonDiameter * _ScaleFactor.Height);
}
}
private int _CenterButtonDiameter = 32;
/// <summary>
/// Indicates diameter of center button of radial menu.
/// </summary>
[DefaultValue(32), Category("Appearance"), Description("Indicates diameter of center button of radial menu.")]
public int CenterButtonDiameter
{
get { return _CenterButtonDiameter; }
set
{
if (value != _CenterButtonDiameter)
{
int oldValue = _CenterButtonDiameter;
_CenterButtonDiameter = value;
OnCenterButtonDiameterChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when CenterButtonDiameter property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnCenterButtonDiameterChanged(int oldValue, int newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("CenterButtonDiameter"));
}
private int _SubMenuEdgeWidth = 18;
/// <summary>
/// Specifies the width of the sub-menu edge around the radial menu.
/// </summary>
[DefaultValue(18), Category("Appearance"), Description("Specifies the width of the sub-menu edge around the radial menu.")]
public int SubMenuEdgeWidth
{
get { return _SubMenuEdgeWidth; }
set
{
if (value < 0) value = 0;
if (value != _SubMenuEdgeWidth)
{
int oldValue = _SubMenuEdgeWidth;
_SubMenuEdgeWidth = value;
OnSubMenuEdgeWidthChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when SubMenuEdgeWidth property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnSubMenuEdgeWidthChanged(int oldValue, int newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("SubMenuEdgeWidth"));
NeedRecalcSize = true;
this.Refresh();
}
private int _SubMenuEdgeItemSpacing = 3;
/// <summary>
/// Indicates spacing between sub-menu marking edge and the item.
/// </summary>
[DefaultValue(3), Category("Appearance"), Description("Indicates spacing between sub-menu marking edge and the item.")]
public int SubMenuEdgeItemSpacing
{
get { return _SubMenuEdgeItemSpacing; }
set
{
if (value != _SubMenuEdgeItemSpacing)
{
int oldValue = _SubMenuEdgeItemSpacing;
_SubMenuEdgeItemSpacing = value;
OnSubMenuEdgeItemSpacingChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when SubMenuEdgeItemSpacing property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnSubMenuEdgeItemSpacingChanged(int oldValue, int newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("SubMenuEdgeItemSpacing"));
NeedRecalcSize = true;
this.Refresh();
}
/// <summary>
/// Return Sub Item at specified location
/// </summary>
public override BaseItem ItemAtLocation(int x, int y)
{
SubItemsCollection subItems = GetDisplayCollection();
foreach (BaseItem item in subItems)
{
if (!item.Visible || !item.Displayed) continue;
RadialMenuItem rm = item as RadialMenuItem;
if (rm != null)
{
if (rm.DisplayPath.IsVisible(x, y))
return rm;
}
else if ((item.Visible || IsOnCustomizeMenu) && item.Displayed && item.DisplayRectangle.Contains(x, y))
{
if (m_ViewRectangle.IsEmpty || m_ViewRectangle.Contains(x, y))
return item;
}
}
return null;
//return base.ItemAtLocation(x, y);
}
protected override void Invalidate(Control containerControl)
{
if (this.DesignMode)
{
if (containerControl.InvokeRequired)
containerControl.BeginInvoke(new MethodInvoker(delegate { containerControl.Invalidate(); }));
else
containerControl.Invalidate();
}
else
{
if (containerControl.InvokeRequired)
containerControl.BeginInvoke(new MethodInvoker(delegate { containerControl.Invalidate(m_Rect, true); }));
else
containerControl.Invalidate(m_Rect, true);
}
}
private Point _MenuLocation = Point.Empty;
/// <summary>
/// Indicates the position of top-left corner of radial menu when shown in screen coordinates
/// </summary>
[Category("Behavior"), Description("Indicates the position of top-left corner of radial menu when shown in screen coordinates")]
public Point MenuLocation
{
get { return _MenuLocation; }
set
{
if (value != _MenuLocation)
{
Point oldValue = _MenuLocation;
_MenuLocation = value;
OnMenuLocationChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when MenuLocation property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnMenuLocationChanged(Point oldValue, Point newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("MenuLocation"));
if (_Popup != null) _Popup.Location = newValue;
}
private RadialMenu _RadialMenu;
internal RadialMenu RadialMenu
{
get { return _RadialMenu; }
set
{
if (value != _RadialMenu)
{
RadialMenu oldValue = _RadialMenu;
_RadialMenu = value;
OnRadialMenuChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when RadialMenu property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnRadialMenuChanged(RadialMenu oldValue, RadialMenu newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("RadialMenu"));
}
public override void InternalMouseMove(MouseEventArgs objArg)
{
base.InternalMouseMove(objArg);
UpateHotSubItemInfoIndex(objArg);
}
private void UpateHotSubItemInfoIndex(MouseEventArgs objArg)
{
if (HotSubItem == null && _SubItemsInfo != null)
{
bool found = false;
// Check sub items
for (int i = 0; i < _SubItemsInfo.Length; i++)
{
RadialSubItemInfo info = _SubItemsInfo[i];
if (info != null && info.Path.IsVisible(objArg.X, objArg.Y))
{
HotSubItemInfoIndex = i;
found = true;
break;
}
}
if (!found)
HotSubItemInfoIndex = -1;
}
else
HotSubItemInfoIndex = -1;
}
public override void InternalMouseLeave()
{
HotSubItemInfoIndex = -1;
base.InternalMouseLeave();
}
public override void InternalMouseDown(MouseEventArgs objArg)
{
UpateHotSubItemInfoIndex(objArg);
int hotSubItemInfoIndex = HotSubItemInfoIndex;
if (hotSubItemInfoIndex >= 0)
{
SubItemsCollection displayCollection = GetDisplayCollection();
if (hotSubItemInfoIndex < displayCollection.Count)
{
BaseItem expand = displayCollection[hotSubItemInfoIndex];
if (expand.ShowSubItems && expand.VisibleSubItems > 0)
{
expand.Expanded = true;
return;
}
}
}
else if (ExpandedItem() == null && _InnerBounds.Contains(objArg.Location))
{
this.Expanded = false;
}
base.InternalMouseDown(objArg);
}
Animation.Storyline _CurrentStoryline = null;
private void RunExpandItemAnimation()
{
Animation.Storyline story = new DevComponents.DotNetBar.Animation.Storyline();
story.AutoDispose = true;
Animation.AnimationInt anim = new DevComponents.DotNetBar.Animation.AnimationInt(
new Animation.AnimationRequest(this, "InnerScale", 100, 85),
Animation.AnimationEasing.EaseInCubic, 250);
anim.Animations.Add(new DevComponents.DotNetBar.Animation.AnimationRequest(this, "SubMenuEdgeWidthAnimated", 0, 12));
anim.AutoDispose = true;
story.Animations.Add(anim);
anim = new DevComponents.DotNetBar.Animation.AnimationInt(
new Animation.AnimationRequest(this, "InnerScale", 85, 100),
Animation.AnimationEasing.EaseOutCubic, 250);
anim.Animations.Add(new DevComponents.DotNetBar.Animation.AnimationRequest(this, "SubMenuEdgeWidthAnimated", 12, 0));
anim.AutoDispose = true;
story.Animations.Add(anim);
_CurrentStoryline = story;
story.Run();
}
protected internal override void OnSubItemExpandChange(BaseItem item)
{
NeedRecalcSize = true;
if (this.Expanded)
{
if (_CurrentStoryline == null || _CurrentStoryline.IsDisposed)
{
WaitForCurrentAnimationToComplete();
RunExpandItemAnimation();
}
else
this.Invalidate();
}
HotSubItemInfoIndex = -1;
base.OnSubItemExpandChange(item);
}
private int _HotSubItemInfoIndex = -1;
private int HotSubItemInfoIndex
{
get { return _HotSubItemInfoIndex; }
set
{
if (_HotSubItemInfoIndex != value)
{
_HotSubItemInfoIndex = value;
this.Refresh();
}
}
}
private int _SubMenuEdgeWidthAnimated = 0;
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)]
public int SubMenuEdgeWidthAnimated
{
get { return _SubMenuEdgeWidthAnimated; }
set
{
if (_SubMenuEdgeWidthAnimated != value)
{
_SubMenuEdgeWidthAnimated = value;
this.Refresh();
}
}
}
protected internal override void OnContainerChanged(object objOldContainer)
{
object newContainer = this.ContainerControl;
SetContainerRecursevly(this, newContainer);
//base.OnContainerChanged(objOldContainer);
}
private void SetContainerRecursevly(BaseItem item, object newContainer)
{
foreach (BaseItem c in item.SubItems)
{
c.ContainerControl = newContainer;
SetContainerRecursevly(c, newContainer);
}
}
/// <summary>
/// Gets the current expanded subitem.
/// </summary>
/// <returns></returns>
protected internal override BaseItem ExpandedItem()
{
return GetExpandedItemRecursevly(this);
}
private BaseItem GetExpandedItemRecursevly(BaseItem item)
{
foreach (BaseItem sub in item.SubItems)
{
if (sub.Expanded)
{
BaseItem inner = GetExpandedItemRecursevly(sub);
if (inner != null) return inner;
return sub;
}
}
return null;
}
private int _BackSymbolSize = 18;
/// <summary>
/// Indicates the size of the back symbol that is displayed on center of radial menu
/// </summary>
[DefaultValue(18), Browsable(false), Description("Indicates the size of the back symbol that is displayed on center of radial menu")]
public int BackButtonSymbolSize
{
get { return _BackSymbolSize; }
set
{
if (value != _BackSymbolSize)
{
int oldValue = _BackSymbolSize;
_BackSymbolSize = value;
OnBackSymbolSizeChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when BackSymbolSize property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnBackSymbolSizeChanged(int oldValue, int newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("BackSymbolSize"));
this.Invalidate();
}
private string _BackSymbol = "\uf060";
/// <summary>
/// Specifies the back button symbol.
/// </summary>
[DefaultValue("\uf060"), Category("Appearance"), Description("Specifies the back button symbol.")]
[Editor("DevComponents.DotNetBar.Design.SymbolTypeEditor, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(System.Drawing.Design.UITypeEditor))]
public string BackButtonSymbol
{
get { return _BackSymbol; }
set
{
if (value != _BackSymbol)
{
string oldValue = _BackSymbol;
_BackSymbol = value;
OnBackSymbolChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when BackSymbol property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnBackSymbolChanged(string oldValue, string newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("BackSymbol"));
this.Invalidate();
}
private eSymbolSet _BackButtonSymbolSet = eSymbolSet.Awesome;
/// <summary>
/// Gets or sets the symbol set used to represent the Symbol.
/// </summary>
[Browsable(false), DefaultValue(eSymbolSet.Awesome)]
public eSymbolSet BackButtonSymbolSet
{
get { return _BackButtonSymbolSet; }
set
{
if (_BackButtonSymbolSet != value)
{
eSymbolSet oldValue = _BackButtonSymbolSet;
_BackButtonSymbolSet = value;
OnBackButtonSymbolSetChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when BackButtonSymbolSet property value changes.
/// </summary>
/// <param name="oldValue">Indciates old value</param>
/// <param name="newValue">Indicates new value</param>
protected virtual void OnBackButtonSymbolSetChanged(eSymbolSet oldValue, eSymbolSet newValue)
{
NeedRecalcSize = true;
OnAppearanceChanged();
this.Refresh();
}
private int _MaxItemPieAngle = 90;
/// <summary>
/// Specifies the maximum pie part angle an item will occupy. Maximum is 180, minimum is 1 degree.
/// </summary>
[DefaultValue(90), Category("Appearance"), Description("Specifies the maximum pie part angle an item will occupy. Maximum is 180, minimum is 1 degree.")]
public int MaxItemPieAngle
{
get { return _MaxItemPieAngle; }
set
{
if (value < 0) value = 90;
if (value > 180) value = 180;
if (value != _MaxItemPieAngle)
{
int oldValue = _MaxItemPieAngle;
_MaxItemPieAngle = value;
OnMaxItemPieAngleChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when MaxItemPieAngle property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnMaxItemPieAngleChanged(int oldValue, int newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("MaxItemPieAngle"));
NeedRecalcSize = true;
this.Refresh();
}
private RadialMenuColorTable _Colors = null;
/// <summary>
/// Gets reference to colors used by the radial menu.
/// </summary>
[Category("Appearance"), Description("Gets reference to colors used by the radial menu."), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public RadialMenuColorTable Colors
{
get
{
return _Colors;
}
}
internal static RadialMenuColorTable GetColorTable()
{
if (GlobalManager.Renderer is Office2007Renderer)
return ((Office2007Renderer)GlobalManager.Renderer).ColorTable.RadialMenu;
else
return null;
}
private eRadialMenuType _MenuType = eRadialMenuType.Segment;
/// <summary>
/// Indicates the radial menu type. eRadialMenuType.Radial menu type allows for display of image, text and any sub-menu items.
/// eRadialMenuType.Circular allows only for display of Symbol or Image and it does not display either text or sub-menu items.
/// eRadialMenuType.Circular is designed to be used for single level menus only that don't need text.
/// </summary>
[DefaultValue(eRadialMenuType.Segment), Category("Appearance"), Description("Indicates the radial menu type.")]
public eRadialMenuType MenuType
{
get { return _MenuType; }
set
{
if (value != _MenuType)
{
eRadialMenuType oldValue = _MenuType;
_MenuType = value;
OnMenuTypeChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when MenuType property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnMenuTypeChanged(eRadialMenuType oldValue, eRadialMenuType newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("MenuType"));
this.Refresh();
}
private Size _SymbolTextSize = Size.Empty;
/// <summary>
/// Gets the realized symbol string.
/// </summary>
[Browsable(false)]
public string SymbolRealized
{
get { return _SymbolRealized; }
}
private string _Symbol = "", _SymbolRealized = "";
/// <summary>
/// Indicates the symbol displayed on face of the button instead of the image. Setting the symbol overrides the image setting.
/// </summary>
[DefaultValue(""), Category("Appearance"), Description("Indicates the symbol displayed on face of the button instead of the image. Setting the symbol overrides the image setting.")]
[Editor("DevComponents.DotNetBar.Design.SymbolTypeEditor, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(System.Drawing.Design.UITypeEditor))]
public string Symbol
{
get { return _Symbol; }
set
{
if (value != _Symbol)
{
string oldValue = _Symbol;
_Symbol = value;
OnSymbolChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when Symbol property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnSymbolChanged(string oldValue, string newValue)
{
if (string.IsNullOrEmpty(newValue))
_SymbolRealized = "";
else
_SymbolRealized = Symbols.GetSymbol(newValue);
//OnPropertyChanged(new PropertyChangedEventArgs("Symbol"));
_SymbolTextSize = Size.Empty;
NeedRecalcSize = true;
OnAppearanceChanged();
this.Refresh();
}
private eSymbolSet _SymbolSet = eSymbolSet.Awesome;
/// <summary>
/// Gets or sets the symbol set used to represent the Symbol.
/// </summary>
[Browsable(false), DefaultValue(eSymbolSet.Awesome)]
public eSymbolSet SymbolSet
{
get { return _SymbolSet; }
set
{
if (_SymbolSet != value)
{
eSymbolSet oldValue = _SymbolSet;
_SymbolSet = value;
OnSymbolSetChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when SymbolSet property value changes.
/// </summary>
/// <param name="oldValue">Indciates old value</param>
/// <param name="newValue">Indicates new value</param>
protected virtual void OnSymbolSetChanged(eSymbolSet oldValue, eSymbolSet newValue)
{
NeedRecalcSize = true;
OnAppearanceChanged();
this.Refresh();
}
private float _SymbolSize = 0f;
/// <summary>
/// Indicates the size of the symbol in points.
/// </summary>
[DefaultValue(0f), Category("Appearance"), Description("Indicates the size of the symbol in points.")]
public float SymbolSize
{
get { return _SymbolSize; }
set
{
if (value != _SymbolSize)
{
float oldValue = _SymbolSize;
_SymbolSize = value;
OnSymbolSizeChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when SymbolSize property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnSymbolSizeChanged(float oldValue, float newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("SymbolSize"));
_SymbolTextSize = Size.Empty;
NeedRecalcSize = true;
OnAppearanceChanged();
this.Refresh();
}
private Image _Image;
/// <summary>
/// Gets or sets the image displayed on the item.
/// </summary>
[DefaultValue(null), Category("Appearance"), Description("Indicates image displayed on the item.")]
public Image Image
{
get { return _Image; }
set
{
if (value != _Image)
{
Image oldValue = _Image;
_Image = value;
OnImageChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when Image property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnImageChanged(Image oldValue, Image newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("Image"));
NeedRecalcSize = true;
OnAppearanceChanged();
this.Refresh();
}
#region RadialSubItemInfo
private class RadialSubItemInfo
{
/// <summary>
/// Initializes a new instance of the RadialSubItemInfo class.
/// </summary>
/// <param name="path"></param>
/// <param name="signPath"></param>
/// <param name="itemAngle"></param>
/// <param name="itemPieAngle"></param>
public RadialSubItemInfo(GraphicsPath path, GraphicsPath signPath, int itemAngle, int itemPieAngle)
{
Path = path;
SignPath = signPath;
ItemAngle = itemAngle;
ItemPieAngle = itemPieAngle;
}
public GraphicsPath Path;
public GraphicsPath SignPath;
public int ItemAngle;
public int ItemPieAngle;
public void Dispose()
{
if (Path != null)
Path.Dispose();
if (SignPath != null)
SignPath.Dispose();
Path = null;
}
}
#endregion
#endregion
#region RadialMenuPopupProxy
private class RadialMenuPopupProxy : PopupItem
{
internal RadialMenuContainer _ParentRadialMenu = null;
/// <summary>
/// Initializes a new instance of the RadialMenuPopupProxy class.
/// </summary>
/// <param name="parentRadialMenu"></param>
public RadialMenuPopupProxy(RadialMenuContainer parentRadialMenu)
{
_ParentRadialMenu = parentRadialMenu;
}
protected internal override bool IsAnyOnHandle(IntPtr iHandle)
{
if (_ParentRadialMenu._Popup != null && _ParentRadialMenu._Popup.Handle == iHandle)
return true;
return false;
}
private bool _Expanded = false;
public override bool Expanded
{
get
{
return _Expanded;
}
set
{
if (_Expanded != value)
{
_Expanded = value;
if (!_Expanded && _ParentRadialMenu.Expanded)
_ParentRadialMenu.Expanded = false;
}
}
}
public override void Paint(ItemPaintArgs p)
{
}
public override BaseItem Copy()
{
return new RadialMenuPopupProxy(_ParentRadialMenu);
}
}
private Font _Font;
/// <summary>
/// Specifies font for menu items.
/// </summary>
[DefaultValue(null), Description("Specifies font for menu items."), Category("Appearance")]
public Font Font
{
get { return _Font; }
set
{
if (value != _Font)
{
Font oldValue = _Font;
_Font = value;
OnFontChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when Font property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnFontChanged(Font oldValue, Font newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("Font"));
if (_Popup != null && this.Expanded) _Popup.Invalidate();
}
#endregion
}
/// <summary>
/// Defines available radial menu type.
/// </summary>
public enum eRadialMenuType
{
Segment,
Circular
}
}