/// <summary> /// Draws horizontal grid using Direct2D</summary> /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param> /// <param name="graphRect">Graph rectangle</param> /// <param name="step">Grid step in canvas coordinates</param> /// <param name="color">Grid line color</param> /// <param name="g">Graphics Direct2D drawing surface</param> public static void DrawHorizontalGrid( Matrix transform, RectangleF graphRect, double step, Color color, D2dGraphics g) { double yScale = transform.Elements[3]; RectangleF clientRect = GdiUtil.Transform(transform, graphRect); double screenStep = Math.Abs(yScale * step); int a = ComputeOpacity(screenStep); color = Color.FromArgb(a, color); double start = graphRect.Top - MathUtil.Remainder(graphRect.Top, step) + step; for (double y = start; y < graphRect.Bottom; y += step) { double cy = (y - graphRect.Top) * yScale + clientRect.Top; g.DrawLine(clientRect.Left, (float)cy, clientRect.Right, (float)cy, color); } }
/// <summary> /// Draws a tree-control style expander, which looks like a square with /// a dash (expanded) or a cross (unexpanded).</summary> /// <param name="x">X coordinate of expander top right corner</param> /// <param name="y">Y coordinate of expander top right corner</param> /// <param name="pen">Pen, should be 1 pixel wide</param> /// <param name="size">Size of pin, in pixels</param> /// <param name="pinned">Whether or not expander should appear "expanded"</param> /// <param name="g">Graphics object</param> public static void DrawRightPin(int x, int y, int size, D2dBrush pen, bool pinned, D2dGraphics g) { //g.DrawRectangle(pen, x - size, y, size, size); int rectWidth = size / 4; int rectHeight = 2 * size / 3; int center = size / 2; if (pinned) { g.DrawLine(x + center - size, y + rectHeight, x + center - size, y + size, pen); //lower center-vertical line g.DrawLine(x - size, y + rectHeight, x, y + rectHeight, pen); // middle-horizontal line g.DrawRectangle(new RectangleF(x + rectWidth - size, y, 2 * rectWidth, rectHeight), pen); //g.DrawLine(pen, x + 3 * rectWidth - 1, y, x + 3 * rectWidth - 1, y + rectHeight); // a vertial line next to the right side of the rect g.DrawLine(x + 3 * rectWidth - 1 - size, y, x + 3 * rectWidth - 1 - size, y + rectHeight, pen); // a vertial line next to the right side of the rect } else { g.DrawLine(x, y + center, x - size + rectHeight, y + center, pen); //left center-horizontal line g.DrawLine(x - size + rectHeight, y, x - size + rectHeight, y + size, pen); // middle-vertical line g.DrawRectangle(new RectangleF(x - size, y + (size - rectWidth) / 2 - 1, rectHeight, 2 * rectWidth), pen); g.DrawLine(x - size + rectHeight, y + (size - rectWidth) / 2 + 2 * rectWidth - 2, x - size, y + (size - rectWidth) / 2 + 2 * rectWidth - 2, pen); // a horizontal line next to the bottom side of the rect } }
private void DrawAnnotation(IAnnotation annotation, DiagramDrawingStyle style, D2dGraphics g, bool drawText, RectangleF graphBound) { // fill background Rectangle bounds = annotation.Bounds; Color backColor = m_coloringContext == null ? SystemColors.Info : (Color) m_coloringContext.GetColor(ColoringTypes.BackColor, annotation); // keep the width of border in 1 pixel after transformation to avoid D2d antialiasing away the line float borderThickness = 1.0f/m_scaleX; g.FillRectangle(bounds, backColor); g.DrawRectangle(bounds, ControlPaint.Dark(backColor), borderThickness, null); // draw titlebar if (style == DiagramDrawingStyle.LastSelected || style == DiagramDrawingStyle.Selected) { var titleBarRect = new RectangleF(bounds.X, bounds.Y, bounds.Width, Margin.Top - 1); g.FillRectangle(titleBarRect, ControlPaint.Dark(backColor)); } // line seperate titlebar from text content g.DrawLine(bounds.X, bounds.Y + Margin.Top-1, bounds.X + bounds.Width, bounds.Y + Margin.Top-1, ControlPaint.Dark(backColor), borderThickness); // draw content if (drawText) { var contentBounds = new RectangleF(bounds.X + Margin.Left, bounds.Y + Margin.Top, bounds.Width - Margin.Size.Width, bounds.Height - Margin.Size.Height); contentBounds.Width = Math.Max(contentBounds.Width, MinimumWidth); contentBounds.Height = Math.Max(contentBounds.Height, MinimumHeight); var textBounds = contentBounds; int topLine = 0; D2dTextLayout textLayout = null; if (m_annotationEditors.ContainsKey(annotation)) { var annotationEditor = m_annotationEditors[annotation]; if (annotationEditor.TextLayout.Text != annotation.Text) // text content changed, for example, undo,redo { annotationEditor.ResetText(annotation.Text); } topLine = annotationEditor.TopLine; textLayout = m_annotationEditors[annotation].TextLayout; annotationEditor.VerticalScrollBarVisibe = textLayout.Height > textLayout.LayoutHeight; if (m_annotationEditors[annotation].VerticalScrollBarVisibe) textBounds.Width -= ScrollBarWidth + 2 * ScrollBarMargin; textLayout.LayoutWidth = textBounds.Width; textLayout.LayoutHeight = textBounds.Height; } if (textLayout == null) { // first assume no v-scroll bar needed textLayout = D2dFactory.CreateTextLayout(annotation.Text, m_theme.TextFormat, contentBounds.Width, contentBounds.Height); if (m_theme.TextFormat.Underlined) textLayout.SetUnderline(true, 0, annotation.Text.Length); if (m_theme.TextFormat.Strikeout) textLayout.SetStrikethrough(true, 0, annotation.Text.Length); if (textLayout.Height > textLayout.LayoutHeight) // need v-scroll bar { textLayout.LayoutWidth = contentBounds.Width - ScrollBarWidth - 2*ScrollBarMargin; } m_annotationEditors.Add(annotation, new TextEditor() { TextLayout = textLayout, TextFormat = m_theme.TextFormat, TopLine = topLine, VerticalScrollBarVisibe = textLayout.Height > textLayout.LayoutHeight }); } var annotationData = m_annotationEditors[annotation]; PointF origin = new PointF(contentBounds.Location.X, contentBounds.Location.Y - topLine * m_theme.TextFormat.FontHeight); g.PushAxisAlignedClip(contentBounds); // draw the selection range behind the text. if (annotationData.SelectionLength > 0) { var hitTestMetrics = textLayout.HitTestTextRange(annotationData.SelectionStart, annotationData.SelectionLength, 0, 0); for (int i = 0; i < hitTestMetrics.Length; ++i) { var highlightRect = new RectangleF(hitTestMetrics[i].Point.X, hitTestMetrics[i].Point.Y, hitTestMetrics[i].Width, hitTestMetrics[i].Height); highlightRect.Offset(origin); g.FillRectangle(highlightRect, m_theme.TextHighlightBrush); } } // draw caret if ( style == DiagramDrawingStyle.Selected || style == DiagramDrawingStyle.LastSelected) { textLayout = annotationData.TextLayout; var caretRect = m_annotationEditors[annotation].GetCaretRect(); caretRect.Offset(origin); //g.FillRectangle(caretRect, m_theme.HotBrush); // set Windows caret position if (m_editingText && contentBounds.IntersectsWith(caretRect) && graphBound.IntersectsWith(caretRect) && AdaptedControl.Focused) { var caretClientRect = GdiUtil.Transform(m_transformAdapter.Transform, caretRect); float ratio = m_scaleX*m_theme.TextFormat.FontHeight/CaretHeight; if (ratio > 1.1f || ratio < 0.9f) // adjust caret height { CaretHeight = (int)(m_scaleX*m_theme.TextFormat.FontHeight); User32.DestroyCaret(); User32.CreateCaret(AdaptedControl.Handle, IntPtr.Zero, CaretWidth, CaretHeight); } // align bottom User32.SetCaretPos((int) caretClientRect.X, (int)(caretClientRect.Y + caretClientRect.Height - CaretHeight)); if (!m_rmbPressed) AdaptedControl.HasKeyboardFocus = true; } else HideCaret(); } // draw text g.DrawTextLayout(origin, textLayout, m_theme.TextBrush); g.PopAxisAlignedClip(); // draw v-scroll bar if (contentBounds.Height < textLayout.Height) { float visibleLines = contentBounds.Height / m_theme.TextFormat.FontHeight; float vMin = topLine * textLayout.LayoutHeight / textLayout.LineCount; float vMax = (topLine + visibleLines-1) * textLayout.LayoutHeight / textLayout.LineCount; if (m_scrolling) { var trackBounds = new RectangleF(contentBounds.Right - ScrollBarMargin - ScrollBarWidth, contentBounds.Y, ScrollBarWidth, contentBounds.Height); g.FillRectangle(trackBounds, Color.Gainsboro); } var thumbBounds = new RectangleF(contentBounds.Right - ScrollBarMargin - ScrollBarWidth, contentBounds.Y + vMin, ScrollBarWidth, vMax - vMin); g.FillRectangle(thumbBounds, Color.DimGray); } } else HideCaret(); }
/// <summary> /// Draws the scrubber manipulator and calculates the bounding rectangle on the handle</summary> /// <param name="g">The graphics object to draw with</param> /// <param name="handleRect">The handle's bounding rectangle for pick tests, in view /// coordinates</param> protected virtual void DrawManipulator(D2dGraphics g, out RectangleF handleRect) { Matrix worldToView = Owner.Transform; float viewX = Sce.Atf.GdiUtil.Transform(worldToView, Position); Rectangle clipRectangle = Owner.VisibleClientRectangle; // allow only the arrow portion to be selected handleRect = new RectangleF( viewX - 5, clipRectangle.Top, 10, 7); g.DrawLine(viewX, clipRectangle.Top, viewX, clipRectangle.Bottom, s_color, 1.0f, null); Color handle_color = m_isMoving ? Color.Tomato : s_color; float pos_x = viewX; float pos_y = clipRectangle.Top + 5; s_arrow[0] = new PointF(pos_x - 4, pos_y - 5); s_arrow[1] = new PointF(pos_x - 4, pos_y); s_arrow[2] = new PointF(pos_x - 5, pos_y + 1); s_arrow[3] = new PointF(pos_x - 5, pos_y + 2); s_arrow[4] = new PointF(pos_x, pos_y + 7); s_arrow[5] = new PointF(pos_x + 5, pos_y + 2); s_arrow[6] = new PointF(pos_x + 5, pos_y + 1); s_arrow[7] = new PointF(pos_x + 4, pos_y); s_arrow[8] = new PointF(pos_x + 4, pos_y - 5); //g.FillPolygon(s_arrow, handle_color); // Fill arrow // Draw arrow border with same gray Photoshop uses //g.DrawLines(s_arrow, Color.FromArgb(116, 114, 106), 3.0f); g.DrawLines(s_arrow, handle_color, 2.0f); string label = Position.ToString(CultureInfo.CurrentCulture); g.DrawText(label, Owner.Renderer.TextFormat, new PointF(pos_x + 6, clipRectangle.Top), SystemColors.WindowText); }
/// <summary> /// Draws vertical grid lines using Direct2D</summary> /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param> /// <param name="graphRect">Graph rectangle</param> /// <param name="step">Grid step in canvas coordinates</param> /// <param name="color">Grid line color</param> /// <param name="g">Graphics Direct2D drawing surface</param> public static void DrawVerticalGrid( Matrix transform, RectangleF graphRect, double step, Color color, D2dGraphics g) { double xScale = transform.Elements[0]; RectangleF clientRect = GdiUtil.Transform(transform, graphRect); double screenStep = Math.Abs(xScale * step); int a = ComputeOpacity(screenStep); color = Color.FromArgb(a, color); double start = graphRect.Left - MathUtil.Remainder(graphRect.Left, step) + step; for (double x = start; x < graphRect.Right; x += step) { double cx = (x - graphRect.Left) * xScale + clientRect.Left; g.DrawLine((float)cx, clientRect.Top, (float)cx, clientRect.Bottom, color); } }