/// <summary> /// Internal rendering method. /// </summary> protected virtual void DrawRibbonTabGlowingTop(Rectangle rect, Color c1, Color c2, Color insideColor, MementoRibbonTabGlowing cache) { GraphicsPath outsidePath = new GraphicsPath(); GraphicsPath topPath = new GraphicsPath(); GraphicsPath ellipsePath = new GraphicsPath(); // Create path for a curved border around the tab outsidePath.AddLine(rect.Left, rect.Bottom - 2, rect.Left, rect.Top + 1.5f); outsidePath.AddLine(rect.Left, rect.Top + 1.5f, rect.Left + 2, rect.Top); outsidePath.AddLine(rect.Left + 2, rect.Top, rect.Right - 4, rect.Top); outsidePath.AddLine(rect.Right - 4, rect.Top, rect.Right - 2, rect.Top + 1.5f); outsidePath.AddLine(rect.Right - 2, rect.Top + 1.5f, rect.Right - 2, rect.Bottom - 2); // Create path for the top glassy effect int q4 = rect.Height / 4; topPath.AddLine(rect.Left + 2, rect.Top + 1, rect.Left + 1, rect.Top + 2); topPath.AddLine(rect.Left + 1, rect.Top + 2, rect.Left + 1, rect.Top + 2 + q4); topPath.AddLine(rect.Left + 1, rect.Top + 2 + q4, rect.Left + 4, rect.Top + 5 + q4); topPath.AddLine(rect.Left + 4, rect.Top + 5 + q4, rect.Right - 5, rect.Top + 5 + q4); topPath.AddLine(rect.Right - 5, rect.Top + 5 + q4, rect.Right - 2, rect.Top + 2 + q4); topPath.AddLine(rect.Right - 2, rect.Top + 2 + q4, rect.Right - 2, rect.Top + 2); topPath.AddLine(rect.Right - 2, rect.Top + 2, rect.Right - 3, rect.Top + 1); RectangleF topRectF = new RectangleF(rect.Left, rect.Top, rect.Width, q4 + 5); cache.topBrush = new LinearGradientBrush(topRectF, c1, Color.Transparent, 90f); int ellipseWidth = (int)(rect.Width * 1.2f); int ellipseHeight = (int)(rect.Height * 0.4f); cache.fullRect = new RectangleF(rect.Left + 1, rect.Top + 1, rect.Width - 3, rect.Height - 2); cache.ellipseRect = new RectangleF(rect.Left - ((ellipseWidth - rect.Width) / 2), rect.Bottom - ellipseHeight, ellipseWidth, ellipseHeight * 2); // Cannot draw a path that contains a zero sized element if ((cache.ellipseRect.Width > 0) && (cache.ellipseRect.Height > 0)) { ellipsePath.AddEllipse(cache.ellipseRect); cache.ellipseBrush = new PathGradientBrush(ellipsePath); cache.ellipseBrush.CenterColor = c2; PointF centerPoint = new PointF(cache.ellipseRect.Left + (cache.ellipseRect.Width / 2), cache.ellipseRect.Top + (cache.ellipseRect.Height / 2)); cache.ellipseBrush.CenterPoint = centerPoint; cache.ellipseBrush.SurroundColors = new Color[] { Color.Transparent }; } cache.insideBrush = new SolidBrush(insideColor); cache.insidePen = new Pen(insideColor); cache.outsidePen = new Pen(c1); cache.outsidePath = outsidePath; cache.topPath = topPath; cache.ellipsePath = ellipsePath; }
/// <summary> /// Internal rendering method. /// </summary> protected virtual IDisposable DrawRibbonTabGlowing(PaletteRibbonShape shape, RenderContext context, Rectangle rect, PaletteState state, IPaletteRibbonBack palette, VisualOrientation orientation, IDisposable memento) { if ((rect.Width > 0) && (rect.Height > 0)) { Color c1 = palette.GetRibbonBackColor1(state); Color c2 = palette.GetRibbonBackColor2(state); Color insideColor = Color.FromArgb(36, c2); bool generate = true; MementoRibbonTabGlowing cache; // Access a cache instance and decide if cache resources need generating if ((memento == null) || !(memento is MementoRibbonTabGlowing)) { if (memento != null) memento.Dispose(); cache = new MementoRibbonTabGlowing(rect, c1, c2, insideColor, orientation); memento = cache; } else { cache = (MementoRibbonTabGlowing)memento; generate = !cache.UseCachedValues(rect, c1, c2, insideColor, orientation); } // Do we need to generate the contents of the cache? if (generate) { // Dispose of existing values cache.Dispose(); switch (orientation) { case VisualOrientation.Top: DrawRibbonTabGlowingTop(rect, c1, c2, insideColor, cache); break; case VisualOrientation.Left: DrawRibbonTabGlowingLeft(rect, c1, c2, insideColor, cache); break; case VisualOrientation.Right: DrawRibbonTabGlowingRight(rect, c1, c2, insideColor, cache); break; case VisualOrientation.Bottom: DrawRibbonTabGlowingBottom(rect, c1, c2, insideColor, cache); break; } } // Fill the path area with inside color context.Graphics.FillPath(cache.insideBrush, cache.outsidePath); switch (orientation) { case VisualOrientation.Top: // Draw the missing line from the bottom of the inside area context.Graphics.DrawLine(cache.insidePen, rect.Left + 1, rect.Bottom - 2, rect.Right - 2, rect.Bottom - 2); break; case VisualOrientation.Left: // Draw the missing line from the right of the inside area context.Graphics.DrawLine(cache.insidePen, rect.Right - 2, rect.Top + 1, rect.Right - 2, rect.Bottom - 2); break; } // Draw the border over the edge of the inside color using (AntiAlias aa = new AntiAlias(context.Graphics)) context.Graphics.DrawPath(cache.outsidePen, cache.outsidePath); // Draw the top glass effect context.Graphics.FillPath(cache.topBrush, cache.topPath); // Cannot draw a path that contains a zero sized element if ((cache.ellipseRect.Width > 0) && (cache.ellipseRect.Height > 0)) context.Graphics.FillRectangle(cache.ellipseBrush, cache.fullRect); } return memento; }