|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
namespace System.Windows.Forms.Design.Behavior;
internal sealed class ToolStripPanelSelectionGlyph : ControlBodyGlyph
{
private readonly ToolStripPanel? _relatedPanel;
private readonly BehaviorService? _behaviorService;
private Rectangle _glyphBounds;
private Bitmap? _image;
private Control? _baseParent;
private bool _isExpanded;
private const int ImageWidthOriginal = 50;
private const int ImageHeightOriginal = 6;
private readonly int _imageWidth = ImageWidthOriginal;
private readonly int _imageHeight = ImageHeightOriginal;
internal ToolStripPanelSelectionGlyph(Rectangle bounds, Cursor cursor, IComponent relatedComponent, IServiceProvider? _provider, ToolStripPanelSelectionBehavior behavior) : base(bounds, cursor, relatedComponent, behavior)
{
_relatedPanel = relatedComponent as ToolStripPanel;
_behaviorService = _provider?.GetService<BehaviorService>();
if (_behaviorService is null)
{
return;
}
IDesignerHost? host = _provider?.GetService<IDesignerHost>();
if (host is null)
{
return;
}
UpdateGlyph();
}
public bool IsExpanded
{
get => _isExpanded;
set
{
if (value != _isExpanded)
{
_isExpanded = value;
UpdateGlyph();
}
}
}
public void UpdateGlyph()
{
if (_behaviorService is null)
{
return;
}
Rectangle translatedBounds = _behaviorService.ControlRectInAdornerWindow(_relatedPanel!);
// Reset the glyph.
_glyphBounds = Rectangle.Empty;
// Refresh the parent
ToolStripContainer? parent = _relatedPanel?.Parent as ToolStripContainer;
if (parent is not null)
{
// get the control to which ToolStripContainer is added.
_baseParent = parent.Parent;
}
if (_image is not null)
{
_image.Dispose();
_image = null;
}
if (!_isExpanded)
{
CollapseGlyph(translatedBounds);
}
else
{
ExpandGlyph(translatedBounds);
}
}
private void SetBitmap(string fileName)
{
_image = new Bitmap(typeof(ToolStripPanelSelectionGlyph), fileName);
_image.MakeTransparent(Color.Magenta);
_image = ScaleHelper.ScaleToDpi(_image, ScaleHelper.InitialSystemDpi, disposeBitmap: true);
}
private void CollapseGlyph(Rectangle bounds)
{
DockStyle? dock = _relatedPanel?.Dock;
int x = 0;
int y = 0;
switch (dock)
{
case DockStyle.Top:
SetBitmap("TopOpen");
x = (bounds.Width - _imageWidth) / 2;
if (x > 0)
{
_glyphBounds = new Rectangle(bounds.X + x, bounds.Y + bounds.Height, _imageWidth, _imageHeight);
}
break;
case DockStyle.Bottom:
SetBitmap("BottomOpen");
x = (bounds.Width - _imageWidth) / 2;
if (x > 0)
{
_glyphBounds = new Rectangle(bounds.X + x, bounds.Y - _imageHeight, _imageWidth, _imageHeight);
}
break;
case DockStyle.Left:
SetBitmap("LeftOpen");
y = (bounds.Height - _imageWidth) / 2;
if (y > 0)
{
_glyphBounds = new Rectangle(bounds.X + bounds.Width, bounds.Y + y, _imageHeight, _imageWidth);
}
break;
case DockStyle.Right:
SetBitmap("RightOpen");
y = (bounds.Height - _imageWidth) / 2;
if (y > 0)
{
_glyphBounds = new Rectangle(bounds.X - _imageHeight, bounds.Y + y, _imageHeight, _imageWidth);
}
break;
default:
throw new NotSupportedException(SR.ToolStripPanelGlyphUnsupportedDock);
}
}
private void ExpandGlyph(Rectangle bounds)
{
DockStyle? dock = _relatedPanel?.Dock;
int x = 0;
int y = 0;
switch (dock)
{
case DockStyle.Top:
SetBitmap("TopClose");
x = (bounds.Width - _imageWidth) / 2;
if (x > 0)
{
_glyphBounds = new Rectangle(bounds.X + x, bounds.Y + bounds.Height, _imageWidth, _imageHeight);
}
break;
case DockStyle.Bottom:
SetBitmap("BottomClose");
x = (bounds.Width - _imageWidth) / 2;
if (x > 0)
{
_glyphBounds = new Rectangle(bounds.X + x, bounds.Y - _imageHeight, _imageWidth, _imageHeight);
}
break;
case DockStyle.Left:
SetBitmap("LeftClose");
y = (bounds.Height - _imageWidth) / 2;
if (y > 0)
{
_glyphBounds = new Rectangle(bounds.X + bounds.Width, bounds.Y + y, _imageHeight, _imageWidth);
}
break;
case DockStyle.Right:
SetBitmap("RightClose");
y = (bounds.Height - _imageWidth) / 2;
if (y > 0)
{
_glyphBounds = new Rectangle(bounds.X - _imageHeight, bounds.Y + y, _imageHeight, _imageWidth);
}
break;
default:
throw new InvalidOperationException(SR.ToolStripPanelGlyphUnsupportedDock);
}
}
/// <summary>
/// The bounds of this Glyph.
/// </summary>
public override Rectangle Bounds => _glyphBounds;
/// <summary>
/// Simple hit test rule: if the point is contained within the bounds
/// then it is a positive hit test.
/// </summary>
public override Cursor? GetHitTest(Point p)
{
if (_behaviorService is null || _baseParent is null)
{
return null;
}
Rectangle baseParentBounds = _behaviorService.ControlRectInAdornerWindow(_baseParent);
return _glyphBounds != Rectangle.Empty && baseParentBounds.Contains(_glyphBounds) && _glyphBounds.Contains(p) ? Cursors.Hand : null;
}
/// <summary>
/// Very simple paint logic.
/// </summary>
public override void Paint(PaintEventArgs pe)
{
if (_behaviorService is null || _baseParent is null)
{
return;
}
Rectangle baseParentBounds = _behaviorService.ControlRectInAdornerWindow(_baseParent);
if (_relatedPanel!.Visible && _image is not null && _glyphBounds != Rectangle.Empty && baseParentBounds.Contains(_glyphBounds))
{
pe.Graphics.DrawImage(_image, _glyphBounds.Left, _glyphBounds.Top);
}
}
}
|