346 lines
18 KiB
C#
346 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using System.Drawing.Drawing2D;
|
|
using DevComponents.DotNetBar.Metro.ColorTables;
|
|
|
|
namespace DevComponents.DotNetBar.Metro.Rendering
|
|
{
|
|
internal class MetroTileItemPainter : MetroRenderer
|
|
{
|
|
private static readonly int InflatePixels = 1;
|
|
private static readonly int InflatePixelsMouseDown = 2;
|
|
private static readonly int DragEffectInflatePixels = -4;
|
|
private static readonly int DragInsertOffsetPixels = 10;
|
|
|
|
//private static readonly Point ImageIndent = new Point(2, 2);
|
|
public override void Render(MetroRendererInfo renderingInfo)
|
|
{
|
|
MetroTileItem item = (MetroTileItem)renderingInfo.Control;
|
|
if (item.Frames.Count == 0)
|
|
{
|
|
using (HatchBrush brush = new HatchBrush(HatchStyle.ForwardDiagonal, Color.Red))
|
|
renderingInfo.PaintEventArgs.Graphics.FillRectangle(brush, item.Bounds);
|
|
return;
|
|
}
|
|
|
|
Matrix currentTransform = null;
|
|
float zoom = 0.95f;
|
|
System.Drawing.Drawing2D.Matrix mx = null;
|
|
|
|
if (renderingInfo.ItemPaintArgs.DragInProgress)
|
|
{
|
|
currentTransform = renderingInfo.PaintEventArgs.Graphics.Transform;
|
|
|
|
mx = new System.Drawing.Drawing2D.Matrix(zoom, 0, 0, zoom, 0, 0);
|
|
float offsetX = (item.WidthInternal * (1.0f / zoom) - item.WidthInternal) / 2;
|
|
float offsetY = (item.HeightInternal * (1.0f / zoom) - item.HeightInternal) / 2;
|
|
mx.Translate(offsetX, offsetY);
|
|
renderingInfo.PaintEventArgs.Graphics.Transform = mx;
|
|
}
|
|
|
|
if (item.CurrentFrameOffset != 0 && item.LastFrame != item.CurrentFrame)
|
|
{
|
|
Graphics g = renderingInfo.PaintEventArgs.Graphics;
|
|
if (currentTransform == null)
|
|
currentTransform = g.Transform;
|
|
g.TranslateTransform(0, -(item.HeightInternal - item.CurrentFrameOffset - InflatePixels * 2), MatrixOrder.Append);
|
|
// Draw last frame first then offset the current frame
|
|
RenderFrame(renderingInfo, item.LastFrame);
|
|
if (mx != null)
|
|
g.Transform = mx;
|
|
else
|
|
g.Transform = currentTransform;
|
|
g.TranslateTransform(0, item.CurrentFrameOffset, MatrixOrder.Append);
|
|
|
|
RenderFrame(renderingInfo, item.CurrentFrame);
|
|
}
|
|
else
|
|
RenderFrame(renderingInfo, item.CurrentFrame);
|
|
|
|
if (currentTransform != null)
|
|
{
|
|
renderingInfo.PaintEventArgs.Graphics.Transform = currentTransform;
|
|
currentTransform.Dispose();
|
|
}
|
|
}
|
|
private void RenderFrame(MetroRendererInfo renderingInfo, int frameIndex)
|
|
{
|
|
MetroTileItem item = (MetroTileItem)renderingInfo.Control;
|
|
MetroTileFrame frame = item.Frames[frameIndex];
|
|
MetroTileColorTable colorTable = renderingInfo.ColorTable.MetroTile;
|
|
Graphics g = renderingInfo.PaintEventArgs.Graphics;
|
|
Rectangle bounds = item.Bounds;
|
|
Region clip = null;
|
|
if (!item.DragStartPoint.IsEmpty) // When dragging tile moves with the mouse
|
|
{
|
|
bounds.Location = renderingInfo.ItemPaintArgs.ContainerControl.PointToClient(Control.MousePosition);
|
|
bounds.Location.Offset(-item.DragStartPoint.X, -item.DragStartPoint.Y);
|
|
clip = g.Clip;
|
|
g.SetClip(bounds, CombineMode.Replace);
|
|
}
|
|
Control control = item.ContainerControl as Control;
|
|
bounds.Inflate(-InflatePixels, -InflatePixels);
|
|
if (item.IsLeftMouseButtonDown)
|
|
bounds.Inflate(-InflatePixelsMouseDown, -InflatePixelsMouseDown);
|
|
else if (item.IsMouseOver)
|
|
bounds.Inflate(InflatePixels, InflatePixels);
|
|
|
|
//if (renderingInfo.ItemPaintArgs.DragInProgress)
|
|
// bounds.Inflate(DragEffectInflatePixels, DragEffectInflatePixels);
|
|
|
|
eDesignInsertPosition insertMarker = item.DesignInsertMarker;
|
|
if (insertMarker == eDesignInsertPosition.After)
|
|
{
|
|
if (item.IsDesignMarkHorizontal)
|
|
bounds.Offset(-DragInsertOffsetPixels, 0);
|
|
else
|
|
bounds.Offset(0, -DragInsertOffsetPixels);
|
|
g.ResetClip();
|
|
}
|
|
else if (insertMarker == eDesignInsertPosition.Before)
|
|
{
|
|
if (item.IsDesignMarkHorizontal)
|
|
bounds.Offset(DragInsertOffsetPixels, 0);
|
|
else
|
|
bounds.Offset(0, DragInsertOffsetPixels);
|
|
g.ResetClip();
|
|
}
|
|
|
|
bool dispose = false;
|
|
bool enabled = item.GetEnabled(renderingInfo.ItemPaintArgs.ContainerControl);
|
|
ElementStyle style = ElementStyleDisplay.GetElementStyle(frame.EffectiveStyle, out dispose);
|
|
|
|
if (bounds.Width > 2048) bounds.Width = 2048;
|
|
if (bounds.Height > 1600) bounds.Height = 1600;
|
|
|
|
if (enabled)
|
|
{
|
|
ElementStyleDisplayInfo di = new ElementStyleDisplayInfo(style, g, bounds);
|
|
ElementStyleDisplay.Paint(di);
|
|
}
|
|
else
|
|
{
|
|
using (SolidBrush brush = new SolidBrush(item.DisabledBackColor.IsEmpty ? renderingInfo.ColorTable.MetroPartColors.CanvasColorLighterShade : item.DisabledBackColor))
|
|
g.FillRectangle(brush, bounds);
|
|
}
|
|
|
|
Rectangle textRect = bounds;
|
|
textRect.X += style.PaddingLeft;
|
|
textRect.Y += style.PaddingTop;
|
|
textRect.Width -= style.PaddingHorizontal;
|
|
textRect.Height -= style.PaddingVertical;
|
|
if (item.IsLeftMouseButtonDown)
|
|
{
|
|
textRect.Width += InflatePixelsMouseDown*2;
|
|
textRect.Height += InflatePixelsMouseDown*2;
|
|
}
|
|
else if(item.IsMouseOver)
|
|
textRect.Inflate(-InflatePixels, -InflatePixels);
|
|
Size tileSize = Dpi.Size(item.TileSize);
|
|
if (item.SubItems.Count > 0 && frameIndex < item.SubItems.Count)
|
|
{
|
|
BaseItem child = item.SubItems[frameIndex];
|
|
if (child.Displayed)
|
|
{
|
|
child.TopInternal = bounds.Y + style.PaddingTop + ((bounds.Height - style.PaddingTop - frame.TitleTextBounds.Height) - child.HeightInternal) / 2;
|
|
child.LeftInternal = bounds.X + style.PaddingLeft;
|
|
child.WidthInternal = tileSize.Width - style.PaddingHorizontal;
|
|
child.Paint(renderingInfo.ItemPaintArgs);
|
|
}
|
|
}
|
|
|
|
Image image = frame.Image;
|
|
ContentAlignment imageTextAlign = frame.ImageTextAlignment;
|
|
Color textColor = enabled ? style.TextColor : renderingInfo.ColorTable.MetroPartColors.CanvasColorLightShade;
|
|
Color symbolColor = textColor;
|
|
if (!frame.SymbolColor.IsEmpty) symbolColor = frame.SymbolColor;
|
|
if (image != null || !string.IsNullOrEmpty(frame.SymbolRealized))
|
|
{
|
|
Font symFont = null;
|
|
Rectangle imageRect = Rectangle.Empty;
|
|
if (string.IsNullOrEmpty(frame.SymbolRealized))
|
|
imageRect = new Rectangle(0, 0, Dpi.ImageWidth(image.Width), Dpi.ImageHeight(image.Height));
|
|
else
|
|
{
|
|
symFont = Symbols.GetFont(frame.SymbolSize, frame.SymbolSet);
|
|
Size imageSize = TextDrawing.MeasureString(g, frame.SymbolRealized, symFont);
|
|
int descent = (int)Math.Ceiling((symFont.FontFamily.GetCellDescent(symFont.Style) *
|
|
symFont.Size / symFont.FontFamily.GetEmHeight(symFont.Style)));
|
|
imageSize.Height -= descent;
|
|
imageRect = new Rectangle(0, 0, imageSize.Width, imageSize.Height);
|
|
}
|
|
|
|
imageRect.Offset(bounds.Location);
|
|
|
|
if (imageTextAlign == ContentAlignment.TopLeft)
|
|
{
|
|
textRect.X += (imageRect.Width + frame.ImageIndent.X);
|
|
textRect.Width -= (imageRect.Width + frame.ImageIndent.X);
|
|
imageRect.Offset(frame.ImageIndent.X, frame.ImageIndent.Y);
|
|
}
|
|
else if (imageTextAlign == ContentAlignment.TopCenter)
|
|
{
|
|
imageRect.X += (tileSize.Width - imageRect.Width) / 2;
|
|
imageRect.Offset(frame.ImageIndent.X, frame.ImageIndent.Y);
|
|
textRect.Y += (imageRect.Height + frame.ImageIndent.Y);
|
|
textRect.Height -= (imageRect.Height);
|
|
}
|
|
else if (imageTextAlign == ContentAlignment.TopRight)
|
|
{
|
|
imageRect.X += (tileSize.Width - imageRect.Width - frame.ImageIndent.X);
|
|
imageRect.Offset(0, frame.ImageIndent.Y);
|
|
textRect.Width -= (imageRect.Width + frame.ImageIndent.X);
|
|
}
|
|
else if (imageTextAlign == ContentAlignment.BottomCenter)
|
|
{
|
|
imageRect.Offset((tileSize.Width - imageRect.Width) / 2, tileSize.Height - imageRect.Height);
|
|
imageRect.Offset(frame.ImageIndent.X, frame.ImageIndent.Y);
|
|
textRect.Height -= (imageRect.Height);
|
|
}
|
|
else if (imageTextAlign == ContentAlignment.BottomLeft)
|
|
{
|
|
imageRect.Offset(0, tileSize.Height - imageRect.Height);
|
|
imageRect.Offset(frame.ImageIndent.X, frame.ImageIndent.Y);
|
|
textRect.X += (imageRect.Width + frame.ImageIndent.X);
|
|
textRect.Width -= (imageRect.Width + frame.ImageIndent.X);
|
|
}
|
|
else if (imageTextAlign == ContentAlignment.BottomRight)
|
|
{
|
|
imageRect.Offset((tileSize.Width - imageRect.Width - frame.ImageIndent.X), tileSize.Height - imageRect.Height);
|
|
imageRect.Offset(0, frame.ImageIndent.Y);
|
|
textRect.Width -= (imageRect.Width + frame.ImageIndent.X);
|
|
}
|
|
else if (imageTextAlign == ContentAlignment.MiddleCenter)
|
|
{
|
|
imageRect.Offset((tileSize.Width - imageRect.Width) / 2, (tileSize.Height - imageRect.Height) / 2);
|
|
imageRect.Offset(frame.ImageIndent.X, frame.ImageIndent.Y);
|
|
textRect.Height = Math.Max(0, textRect.Bottom - imageRect.Bottom);
|
|
textRect.Y = imageRect.Bottom + 1;
|
|
}
|
|
else if (imageTextAlign == ContentAlignment.MiddleLeft)
|
|
{
|
|
imageRect.Offset(0, (tileSize.Height - imageRect.Height) / 2);
|
|
imageRect.Offset(frame.ImageIndent.X, frame.ImageIndent.Y);
|
|
textRect.X += (imageRect.Width + frame.ImageIndent.X);
|
|
textRect.Width -= (imageRect.Width + frame.ImageIndent.X);
|
|
}
|
|
else if (imageTextAlign == ContentAlignment.MiddleRight)
|
|
{
|
|
imageRect.Offset((tileSize.Width - imageRect.Width - frame.ImageIndent.X), (tileSize.Height - imageRect.Height) / 2);
|
|
imageRect.Offset(0, frame.ImageIndent.Y);
|
|
textRect.Width -= (imageRect.Width + frame.ImageIndent.X);
|
|
}
|
|
else
|
|
imageRect.Offset(frame.ImageIndent.X, frame.ImageIndent.Y);
|
|
|
|
if (string.IsNullOrEmpty(frame.SymbolRealized))
|
|
g.DrawImage(image, imageRect);
|
|
else
|
|
TextDrawing.DrawStringLegacy(g, frame.SymbolRealized, symFont, symbolColor, new Rectangle(imageRect.X, imageRect.Y, 0, 0), eTextFormat.Default);
|
|
}
|
|
|
|
if (textRect.Width > 0 && textRect.Height > 0 && frame.Text != null)
|
|
{
|
|
Font font = renderingInfo.DefaultFont;
|
|
if (style.Font != null)
|
|
font = style.Font;
|
|
bool rightToLeft = renderingInfo.RightToLeft;
|
|
if (frame.TextMarkupBody == null)
|
|
{
|
|
eTextFormat textFormat = eTextFormat.Default | eTextFormat.WordBreak | eTextFormat.NoClipping;
|
|
if (style.TextLineAlignment == eStyleTextAlignment.Center)
|
|
textFormat |= eTextFormat.VerticalCenter;
|
|
else if (style.TextLineAlignment == eStyleTextAlignment.Far)
|
|
textFormat |= eTextFormat.Bottom;
|
|
if (style.TextAlignment == eStyleTextAlignment.Center)
|
|
textFormat |= eTextFormat.HorizontalCenter;
|
|
else if (style.TextAlignment == eStyleTextAlignment.Far)
|
|
textFormat |= eTextFormat.Right;
|
|
//if (frame.Text.Contains("Explorer")) Console.WriteLine("{0} {1}", textRect, DateTime.Now);
|
|
TextDrawing.DrawString(g, frame.Text, font, textColor, textRect, textFormat);
|
|
}
|
|
else
|
|
{
|
|
TextMarkup.MarkupDrawContext d = new TextMarkup.MarkupDrawContext(g, font, textColor, rightToLeft);
|
|
d.HotKeyPrefixVisible = false;
|
|
d.ContextObject = item;
|
|
Rectangle markupBounds = textRect;
|
|
// Can't do this because it will break all apps default for TextLineAlignment is eStyleTextAlignment.Center
|
|
//if (style.TextLineAlignment == eStyleTextAlignment.Center)
|
|
// markupBounds = new Rectangle(new Point(textRect.X, textRect.Y + (textRect.Height - frame.TextMarkupBody.Bounds.Height) / 2), frame.TextMarkupBody.Bounds.Size);
|
|
//else if (style.TextLineAlignment == eStyleTextAlignment.Far)
|
|
// markupBounds = new Rectangle(new Point(textRect.X, textRect.Bottom - frame.TextMarkupBody.Bounds.Height), frame.TextMarkupBody.Bounds.Size);
|
|
|
|
frame.TextMarkupBody.Bounds = markupBounds;
|
|
frame.TextMarkupBody.Render(d);
|
|
}
|
|
}
|
|
|
|
if (frame.TitleText != null)
|
|
{
|
|
Color titleTextColor = enabled ? frame.TitleTextColor : renderingInfo.ColorTable.MetroPartColors.CanvasColorLightShade;
|
|
if (titleTextColor.IsEmpty)
|
|
titleTextColor = style.TextColor;
|
|
Font font = item.GetTitleTextFont(frame, style, control);
|
|
Rectangle titleTextRect = frame.TitleTextBounds;
|
|
titleTextRect.Offset(bounds.Location);
|
|
if (item.IsLeftMouseButtonDown)
|
|
titleTextRect.Offset(1, 1);
|
|
else if (item.IsMouseOver)
|
|
titleTextRect.Offset(InflatePixels, InflatePixels);
|
|
if (frame.TitleTextMarkupBody == null)
|
|
TextDrawing.DrawString(g, frame.TitleText, font, titleTextColor, titleTextRect, eTextFormat.Default | eTextFormat.SingleLine);
|
|
else
|
|
{
|
|
TextMarkup.MarkupDrawContext d = new TextMarkup.MarkupDrawContext(g, font, titleTextColor, renderingInfo.RightToLeft);
|
|
d.HotKeyPrefixVisible = false;
|
|
d.ContextObject = item;
|
|
Rectangle markupBounds = titleTextRect;
|
|
frame.TitleTextMarkupBody.Bounds = markupBounds;
|
|
frame.TitleTextMarkupBody.Render(d);
|
|
}
|
|
}
|
|
|
|
if (item.Checked)
|
|
{
|
|
Size checkMarkSize = Dpi.Size(CheckMarkSize);
|
|
Rectangle markBounds = new Rectangle(bounds.Right - checkMarkSize.Width, bounds.Y, checkMarkSize.Width, checkMarkSize.Height);
|
|
using (GraphicsPath markPath = new GraphicsPath())
|
|
{
|
|
markPath.AddLine(markBounds.X, markBounds.Y, markBounds.Right - 1, markBounds.Y);
|
|
markPath.AddLine(markBounds.Right - 1, markBounds.Y, markBounds.Right - 1, markBounds.Bottom - 1);
|
|
markPath.CloseFigure();
|
|
using (SolidBrush brush = new SolidBrush(colorTable.CheckBackground))
|
|
g.FillPath(brush, markPath);
|
|
}
|
|
using (SolidBrush brush = new SolidBrush(colorTable.CheckForeground))
|
|
{
|
|
Rectangle checkCircleBounds = new Rectangle();
|
|
checkCircleBounds.Size = new Size(Dpi.Width11, Dpi.Height11);
|
|
checkCircleBounds.X = markBounds.Right - checkCircleBounds.Size.Width - Dpi.Width3;
|
|
checkCircleBounds.Y = markBounds.Y + Dpi.Height2;
|
|
using (Pen pen = new Pen(colorTable.CheckForeground, Dpi.Width2))
|
|
{
|
|
g.DrawEllipse(pen, checkCircleBounds);
|
|
g.DrawLine(pen, checkCircleBounds.X + Dpi.Width3, checkCircleBounds.Y + Dpi.Height5, checkCircleBounds.X + Dpi.Width6, checkCircleBounds.Y + Dpi.Height8);
|
|
g.DrawLine(pen, checkCircleBounds.X + Dpi.Width6, checkCircleBounds.Y + Dpi.Height8, checkCircleBounds.X + Dpi.Width9, checkCircleBounds.Y + Dpi.Height3);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dispose) style.Dispose();
|
|
|
|
if (clip != null)
|
|
{
|
|
g.Clip = clip;
|
|
clip.Dispose();
|
|
}
|
|
}
|
|
|
|
private static readonly Size CheckMarkSize = new Size(27, 27);
|
|
}
|
|
}
|