/// <summary> /// Draws the attributes /// </summary> private async Task <PaintContext> PaintAttributes(PaintContext paintContext, string attributesString, bool isSelected, IGraphics gfx) { paintContext = paintContext.Clone(); if (string.IsNullOrWhiteSpace(attributesString)) { return(paintContext); } var attributeWidth = await this.GetAttributeTextWidth(attributesString, gfx); // draw a frame around the attributes StandardNodeTagPaint.DrawNodeBodyBySize(GfxJob.Layers.AttributeBackground, paintContext.PaintPosX, paintContext.PaintPosY + this.dimensions.AttributeMarginY, attributeWidth, this.dimensions.AttributeHeight, 2, isSelected ? this.config.ColorNodeAttributeBackground.InvertedColor : this.config.ColorNodeAttributeBackground, isSelected ? this.config.ColorNodeTagBorder.InvertedColor : this.config.ColorNodeTagBorder, gfx); // Draw attributes gfx.AddJob(new JobDrawString { Batchable = false, Layer = GfxJob.Layers.Text, Text = attributesString.ToString(), Color = isSelected ? this.config.ColorText.InvertedColor : this.config.ColorText, X = paintContext.PaintPosX, Y = paintContext.PaintPosY + this.dimensions.AttributeMarginY + this.dimensions.AttributeInnerMarginY + 1, Font = config.FontNodeAttribute }); // Set character cursor behind the attributes paintContext.PaintPosX += attributeWidth + this.dimensions.InnerMarginX; return(paintContext); }
protected override async Task <PaintContext> PaintInternal(PaintContext paintContext, string attributesString, bool isSelected, IGraphics gfx) { var esteemedWidth = this.nodeNameTextWidth + this.dimensions.InnerMarginX * 3; if (paintContext.PaintPosX + esteemedWidth > paintContext.LimitRight) { paintContext.HeightActualRow = Math.Max(paintContext.HeightActualRow, config.MinLineHeight); paintContext.PaintPosX = paintContext.LimitLeft + this.config.ChildIndentX; paintContext.PaintPosY += paintContext.HeightActualRow; paintContext.HeightActualRow = config.MinLineHeight; } var startX = paintContext.PaintPosX; var startY = paintContext.PaintPosY; paintContext.PaintPosX += this.dimensions.InnerMarginX; // margin to left border // draw node name gfx.AddJob(new JobDrawString { Batchable = false, Layer = GfxJob.Layers.Text, Text = this.node.Name, Color = isSelected ? this.config.ColorText.InvertedColor : this.config.ColorText, X = paintContext.PaintPosX, Y = paintContext.PaintPosY + this.config.InnerMarginY, Font = this.config.FontNodeName }); paintContext.PaintPosX += nodeNameTextWidth + this.dimensions.InnerMarginX; // draw the attributes paintContext = await this.PaintAttributes(paintContext, attributesString, isSelected, gfx); // standard distance + one pixel to the right, otherwise we draw on the frame line paintContext.PaintPosX += 1; var borderWidth = paintContext.PaintPosX - startX; StandardNodeTagPaint.DrawNodeBodyBySize( GfxJob.Layers.TagBackground, startX, paintContext.PaintPosY, borderWidth, this.config.TagHeight, this.dimensions.CornerRadius, isSelected ? this.dimensions.BackgroundColor.InvertedColor : this.dimensions.BackgroundColor, isSelected ? this.config.ColorNodeTagBorder.InvertedColor : this.config.ColorNodeTagBorder, gfx); // if necessary draw the continuing arrow at the end of the frame if (this.isClosingTagVisible) { var point1 = new Point(paintContext.PaintPosX, paintContext.PaintPosY + this.config.InnerMarginY); var point2 = new Point(paintContext.PaintPosX + this.dimensions.InnerMarginX, paintContext.PaintPosY + this.config.TagHeight / 2); var point3 = new Point(paintContext.PaintPosX, paintContext.PaintPosY + this.config.TagHeight - this.config.InnerMarginY); gfx.AddJob(new JobDrawPolygon { Batchable = true, Layer = GfxJob.Layers.TagBorder, FillColor = isSelected ? this.config.ColorNodeTagBorder.InvertedColor : this.config.ColorNodeTagBorder, Points = new[] { point1, point2, point3 } }); // Remember the right arrow area this.AreaArrow = new Rectangle(paintContext.PaintPosX, paintContext.PaintPosY, this.dimensions.InnerMarginX, this.config.TagHeight); paintContext.PaintPosX += this.dimensions.InnerMarginX; } else { this.AreaArrow = null; } paintContext.HeightActualRow = System.Math.Max(paintContext.HeightActualRow, this.config.MinLineHeight); // See how high the current line is // Remember where the mouse areas are this.AreaTag = new Rectangle(startX - 2, startY, paintContext.PaintPosX + 2 - (startX), this.config.TagHeight); paintContext.FoundMaxX = System.Math.Max(paintContext.FoundMaxX, paintContext.PaintPosX); this.lastPaintContextResult = paintContext.Clone(); return(paintContext.Clone()); }
protected override async Task <PaintContext> PaintInternal(PaintContext paintContext, string attributesString, bool isSelected, IGraphics gfx) { var startX = paintContext.PaintPosX; var esteemedWidth = this.nodeNameTextWidth + this.dimensions.InnerMarginX * 3; if (paintContext.PaintPosX + esteemedWidth > paintContext.LimitRight) { paintContext.HeightActualRow = Math.Max(paintContext.HeightActualRow, config.MinLineHeight); paintContext.PaintPosX = paintContext.LimitLeft + this.config.ChildIndentX; paintContext.PaintPosY += paintContext.HeightActualRow; paintContext.HeightActualRow = config.MinLineHeight; } // draw an arrow to the left in front of the node frame // arrow to left Point point1 = new Point(paintContext.PaintPosX + this.dimensions.InnerMarginX, paintContext.PaintPosY + this.config.InnerMarginY); Point point2 = new Point(paintContext.PaintPosX + this.dimensions.InnerMarginX, paintContext.PaintPosY + this.config.TagHeight - this.config.InnerMarginY); Point point3 = new Point(paintContext.PaintPosX, paintContext.PaintPosY + this.config.TagHeight / 2); gfx.AddJob(new JobDrawPolygon { Batchable = true, Layer = GfxJob.Layers.TagBorder, FillColor = isSelected ? this.config.ColorNodeTagBorder.InvertedColor : this.config.ColorNodeTagBorder, Points = new[] { point1, point2, point3 } }); // Remember the right arrow area this.AreaArrow = new Rectangle(paintContext.PaintPosX, paintContext.PaintPosY, this.dimensions.InnerMarginX, this.config.TagHeight); paintContext.PaintPosX += this.dimensions.InnerMarginX + 1; // Place drawing cursor behind the arrow // ## Draw frame for closing node ### StandardNodeTagPaint.DrawNodeBodyBySize(GfxJob.Layers.TagBackground, paintContext.PaintPosX, paintContext.PaintPosY, this.nodeNameTextWidth + this.dimensions.InnerMarginX * 2, this.config.TagHeight, this.dimensions.CornerRadius, isSelected ? this.dimensions.BackgroundColor.InvertedColor : this.dimensions.BackgroundColor, isSelected ? this.config.ColorNodeTagBorder.InvertedColor : this.config.ColorNodeTagBorder, gfx); paintContext.PaintPosX += this.dimensions.InnerMarginX; // Distance between frame and font // ## Draw name for closing node ### gfx.AddJob(new JobDrawString { Batchable = false, Layer = GfxJob.Layers.Text, Text = this.node.Name, Color = isSelected ? this.config.ColorText.InvertedColor : this.config.ColorText, X = paintContext.PaintPosX, Y = paintContext.PaintPosY + this.config.InnerMarginY, Font = this.config.FontNodeName }); paintContext.PaintPosX += this.nodeNameTextWidth + this.dimensions.InnerMarginX; // Distance between font and frame // One pixel to the right, because otherwise we draw on the frame line and the cursor flashes on the frame paintContext.PaintPosX++; // Remember where the mouse areas are this.AreaTag = new Rectangle(startX, paintContext.PaintPosY, paintContext.PaintPosX - startX, this.config.TagHeight); paintContext.FoundMaxX = System.Math.Max(paintContext.FoundMaxX, paintContext.PaintPosX); this.lastPaintContextResult = paintContext.Clone(); await Task.CompletedTask; return(paintContext); }
protected override async Task <PaintContext> PaintInternal(PaintContext paintContext, bool cursorBlinkOn, XmlCursor cursor, IGraphics gfx, PaintModes paintMode, int depth) { paintContext.PaintPosX += 3; var actualText = ToolboxXml.TextFromNodeCleaned(XmlNode); var selection = this.CalculateStartAndEndOfSelection(actualText, cursor); var actualPaintData = LastPaintingDataText.CalculateActualPaintData(paintContext, cursorBlinkOn, this.XmlNode, actualText, this.Config.FontTextNode.Height, cursor, selection.Start, selection.Length); var alreadyUnpainted = false; switch (paintMode) { case PaintModes.ForcePaintNoUnPaintNeeded: alreadyUnpainted = true; this.lastPaintData = null; break; case PaintModes.ForcePaintAndUnpaintBefore: alreadyUnpainted = true; this.lastPaintData = null; this.UnPaint(gfx); break; case PaintModes.OnlyPaintWhenChanged: if (!actualPaintData.Equals(lastPaintData)) { this.lastPaintData = null; } break; } if (this.lastPaintData != null && this.lastPaintContextResult != null) { return(lastPaintContextResult.Clone()); } this.lastPaintData = actualPaintData; this.cursorPaintPos = null; if (lastFontHeight != this.Config.FontTextNode.Height) { lastFontHeight = this.Config.FontTextNode.Height; lastCalculatedFontWidth = await this.xmlEditor.NativePlatform.Gfx.MeasureDisplayStringWidthAsync("W", this.Config.FontTextNode); } paintContext.HeightActualRow = Math.Max(paintContext.HeightActualRow, this.Config.MinLineHeight); int marginY = (paintContext.HeightActualRow - this.Config.FontTextNode.Height) / 2; const int charMarginRight = 2; var textPartsRaw = TextSplitHelper.SplitText( text: actualText, invertStart: selection.Start, invertLength: selection.Length, maxLength: (int)((paintContext.LimitRight - paintContext.LimitLeft) / lastCalculatedFontWidth) - charMarginRight, maxLengthFirstLine: (int)((paintContext.LimitRight - paintContext.PaintPosX) / lastCalculatedFontWidth) - charMarginRight) .ToArray(); var newTextParts = this.GetTextLinesFromTextParts(textPartsRaw, paintContext, cursorBlinkOn, cursor, lastCalculatedFontWidth).ToArray(); // Now draw the content, if necessary wrap to several text parts and lines for (int i = 0; i < newTextParts.Length; i++) { var newPart = newTextParts[i]; var oldPart = (this.textParts != null && i < this.textParts.Length) ? this.textParts[i] : null; if (alreadyUnpainted == false && newPart.Equals(oldPart)) { // no need to paint the text part again } else { // draw the inverted background if (!alreadyUnpainted && oldPart != null) { gfx.UnPaintRectangle(oldPart.Rectangle); } if (newPart.Inverted || this.colorBackground != this.Config.ColorBackground) { gfx.AddJob(new JobDrawRectangle { Batchable = true, Layer = GfxJob.Layers.TagBackground, Rectangle = newPart.Rectangle, FillColor = newPart.Inverted ? this.colorBackground.InvertedColor : this.colorBackground, }); } // draw the text gfx.AddJob(new JobDrawString { Batchable = false, Layer = GfxJob.Layers.Text, Text = newPart.Text, Color = newPart.Inverted ? this.colorText.InvertedColor : this.colorText, X = newPart.Rectangle.X, Y = newPart.Rectangle.Y + marginY, Font = Config.FontTextNode });; } paintContext.PaintPosY = newPart.Rectangle.Y; paintContext.PaintPosX = newPart.Rectangle.X + newPart.Rectangle.Width; paintContext.FoundMaxX = Math.Max(paintContext.FoundMaxX, paintContext.PaintPosX); } if (this.textParts != null) // unpaint old text parts out of new parts range { for (int i = newTextParts.Length; i < this.textParts.Length; i++) { gfx.UnPaintRectangle(this.textParts[i].Rectangle); } } this.textParts = newTextParts; paintContext.PaintPosX += 2; this.lastPaintContextResult = paintContext.Clone(); return(paintContext.Clone()); }
public async Task <PaintContext> Paint(PaintContext paintContext, bool cursorIsOnThisNode, bool cursorBlinkOn, bool alreadyUnpainted, bool isSelected, IGraphics gfx) { paintContext.PaintPosX += 1; var startX = paintContext.PaintPosX; var startY = paintContext.PaintPosY; var attributesString = this.GetAttributesString(); if (alreadyUnpainted) { this.lastPaintContextResult = null; } if (this.lastTextWidthFontHeight != this.config.FontNodeName.Height) { this.nodeNameTextWidth = (int)(await gfx.MeasureDisplayStringWidthAsync(this.node.Name, this.config.FontNodeName)); this.lastTextWidthFontHeight = this.config.FontNodeName.Height; lastPaintContextResult = null; } var cursorChanged = false; if (cursorIsOnThisNode) { cursorChanged = cursorBlinkOn != this.lastCursorBlinkOn; } else { cursorChanged = cursorIsOnThisNode != this.lastCursorWasOnThisNode; } if (lastPaintContextResult != null && this.lastPaintX == startX && this.lastPaintY == startY && this.lastPaintWasSelected == isSelected && this.lastAttributeString == attributesString && cursorChanged == false) { return(lastPaintContextResult.Clone()); } if (!alreadyUnpainted) { this.Unpaint(gfx); } this.lastPaintX = startX; this.lastPaintY = startY; this.lastPaintWasSelected = isSelected; this.lastAttributeString = attributesString; this.lastCursorBlinkOn = cursorBlinkOn; this.lastCursorWasOnThisNode = cursorIsOnThisNode; paintContext = await this.PaintInternal(paintContext, attributesString, isSelected, gfx); paintContext.HeightActualRow = Math.Max(paintContext.HeightActualRow, this.config.MinLineHeight); // See how high the current line is paintContext.FoundMaxX = Math.Max(paintContext.FoundMaxX, paintContext.PaintPosX); this.lastPaintContextResult = paintContext.Clone(); return(paintContext.Clone()); }