public override void Paint(IntPtr hdc, ITextSegmentStyled textSegment, ITextView textView, TextSegmentVisualInfo info, int x, int y, int lineHeight, StyleRenderInfo sri) { if (staticBrushRed == null) { staticBrushRed = new SafeHandleGDI(SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(Color.Red))); } var spaceSize = (lineHeight / 4d); var rectTop = new RECT { left = x, top = y, right = x + (lineHeight / 8), bottom = (int)(y + (lineHeight - (spaceSize))) }; var rectBottom = new RECT { left = rectTop.left, top = (int)(rectTop.bottom + (spaceSize / 2)), right = rectTop.right }; rectBottom.bottom = (int)(rectBottom.top + (spaceSize / 2)); SafeNativeMethods.FillRect(hdc, ref rectTop, staticBrushRed.DangerousGetHandle()); SafeNativeMethods.FillRect(hdc, ref rectBottom, staticBrushRed.DangerousGetHandle()); }
public override void Paint(IntPtr hdc, ITextSegmentStyled styledSegment, ITextView textView, TextSegmentVisualInfo info, int x, int y, int lineHeight, StyleRenderInfo sri) { //if (this._paintUnderline == null) //{ // this._paintUnderline = this.Settings.SpellcheckUnderlineEnabled; // Bridge.Get().GetSafe("Text.Style.Spellcheck.Underline.Enabled", true); //} if (textView.Settings.SpellcheckUnderlineEnabled == false) { return; } if (staticPenUnderline == null) { staticUnderlineColor = textView.Settings.ColorSpellcheckUnderline; // Bridge.Get().GetSafe("Text.Style.Spellcheck.Underline.Color", Color.Red); //int underlineType = Bridge.Get().GetSafe("Text.Style.Spellcheck.Underline.Type", (int) PenType.Dot); staticPenUnderline = new SafeHandleGDI(SafeNativeMethods.CreatePen((int)textView.Settings.SpellcheckUnderlineType, -1, ColorTranslator.ToWin32(staticUnderlineColor))); } var wordSize = styledSegment.Parent.GetSize(hdc, x, styledSegment.Index, styledSegment.GetLength(info.TextColumnIndex), info); var previousPen = SafeNativeMethods.SelectObject(hdc, staticPenUnderline.DangerousGetHandle()); var previousBkMode = SafeNativeMethods.SetBkMode(hdc, NativeConstants.TRANSPARENT); SafeNativeMethods.MoveToEx(hdc, x - wordSize.Width, y + lineHeight - 2, IntPtr.Zero); SafeNativeMethods.LineTo(hdc, x, y + lineHeight - 2); SafeNativeMethods.SelectObject(hdc, previousPen); SafeNativeMethods.SetBkMode(hdc, previousBkMode); }
public void Remove(ITextSegmentStyled segment) { for (var i = 0; i < this._items.Count; i++) { if (this._items[i].Segment == segment) { this._items.RemoveAt(i); break; } } }
public bool Add(ITextEditor textEditor, ITextSegmentStyled segment) { var newRsi = new RenderStateItem { Segment = segment }; segment.Style.FillRenderStateItem(textEditor, newRsi); this._items.Add(newRsi); return(true); }
public void AddManualTextSegment(ITextSegmentStyled segmentStyled, int index, int textColumnIndex) { var textAnchor = segmentStyled as TextAnchor; if (textAnchor.TextLine != null) { textAnchor.TextLine = null; } var lineIndex = this.TextHandler.GetLineFromCharIndex(index, textColumnIndex); textAnchor.TextLine = this._lines[lineIndex]; }
public ITextSegmentStyled GetClosest(int index, string ofType) { ITextSegmentStyled closestMatch = null; var foundLineStartIndex = -1; foreach (var textSegmentStyled in this.GetStyledTextSegments()) { if ((textSegmentStyled is TextAnchor) == false) { // This styled text segment is not an anchor, so we of course do not use it. continue; } var anchor = (TextAnchor)textSegmentStyled; if (ofType != null && anchor.Style.NameKey != ofType) { continue; } if (anchor.IndexGlobal > index) { if (foundLineStartIndex != -1 && foundLineStartIndex != anchor.TextLine.Index) { break; } continue; } if (closestMatch == null || anchor.IndexGlobal > closestMatch.IndexGlobal) { foundLineStartIndex = anchor.TextLine.Index; closestMatch = anchor; } } return(closestMatch); }
private void SetFocusedStyleSegment(int globalIndex, bool fromMouse, int textColumIndex) { var previous = this._renderer.FocusedStyledSegment; ITextSegmentStyled focusedStyledSegment = null; foreach (var styledSegment in TextDocument.TextSegmentStyledManager.Get(globalIndex, textColumIndex)) { if (styledSegment.CanExecute == false) { continue; } if (focusedStyledSegment == null) { focusedStyledSegment = styledSegment; } if (styledSegment.CanExecute) { focusedStyledSegment = styledSegment; break; } } this._renderer.FocusedStyledSegment = focusedStyledSegment; if (this._renderer.FocusedStyledSegment != previous) { if (fromMouse && this.ScrollHost.IsScrollingHorizontally == false && this.ScrollHost.IsScrollingVertically == false) { Cursor = focusedStyledSegment == null ? Cursors.IBeam : Cursors.Hand; } Invalidate(); } }
public virtual bool Execute(ITextSegmentStyled styledTextSegment) { return(false); }
public virtual void ShowInfo(ITextSegmentStyled textSegment) { //this.Settings.Notifier.Info("Not implemented yet. Will show some info.", "Text Anchor"); }
public abstract void Paint(IntPtr hdc, ITextSegmentStyled textSegment, ITextView textView, TextSegmentVisualInfo info, int x, int y, int lineHeight, StyleRenderInfo sri);
public override void Paint(IntPtr hdc, ITextSegmentStyled textSegment, ITextView textView, TextSegmentVisualInfo info, int x, int y, int lineHeight, StyleRenderInfo sri) { var index = (int)textSegment.Object; var allSegments = sri.Get <ITextSegmentStyled[]>("speaker.segments"); if (allSegments == null) { allSegments = textView.TextDocument.TextSegmentStyledManager.GetStyledTextSegments(NameKey).ToArray(); sri.Set("speaker.segments", allSegments); } Color color; if (index == -1) { // TODO: Figure out the current speaker's index foreach (var styledSegment in allSegments) { var otherIndex = (int)styledSegment.Object; if (otherIndex == -1) { index = index == 1 ? 2 : 1; } else { index = otherIndex; } if (styledSegment == textSegment) { // We've arrived at our own row, so let's abort now. break; } } } var fill = false; switch (index) { case 1: color = Color.WhiteSmoke; break; case 2: color = Color.FromArgb(242, 255, 22); break; case 3: color = Color.FromArgb(189, 189, 255); break; case 4: color = Color.FromArgb(178, 255, 159); break; case 5: color = Color.FromArgb(255, 189, 189); break; case -2: fill = true; color = Color.FromArgb(255, 0, 0); break; default: color = Color.FromArgb(200, 200, 200); break; } if (fill) { var brush = new SafeHandleGDI(SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(color))); var previousBrush = SafeNativeMethods.SelectObject(hdc, brush.DangerousGetHandle()); var previousBkMode = SafeNativeMethods.SetBkMode(hdc, NativeConstants.TRANSPARENT); var r = new RECT { top = y, right = textView.ClientSize.Width, bottom = y + lineHeight, left = info.Size.Width + 10 }; SafeNativeMethods.FillRect(hdc, ref r, brush.DangerousGetHandle()); SafeNativeMethods.SelectObject(hdc, previousBrush); SafeNativeMethods.SetBkMode(hdc, previousBkMode); } else { var pen = new SafeHandleGDI(SafeNativeMethods.CreatePen(NativeConstants.PS_SOLID, -1, ColorTranslator.ToWin32(color))); var previousPen = SafeNativeMethods.SelectObject(hdc, pen.DangerousGetHandle()); var previousBkMode = SafeNativeMethods.SetBkMode(hdc, NativeConstants.TRANSPARENT); SafeNativeMethods.MoveToEx(hdc, 1, y, IntPtr.Zero); SafeNativeMethods.LineTo(hdc, 1, y + lineHeight); SafeNativeMethods.MoveToEx(hdc, fill ? info.Size.Width : 2, y, IntPtr.Zero); SafeNativeMethods.LineTo(hdc, fill ? info.Size.Width : 2, y + lineHeight); SafeNativeMethods.SelectObject(hdc, previousPen); SafeNativeMethods.SetBkMode(hdc, previousBkMode); } }
public void RemoveTextSegment(ITextSegmentStyled textSegment) { var textAnchor = (textSegment as TextAnchor); textAnchor.TextLine = null; }
/// <summary> /// TODO: Make this threaded and make the text control not editable meanwhile /// </summary> public bool SearchAndApplyTo(ITextView textView, ITextSegment textSegment, int index, int length, bool changeWasFinalizer, int textColumnIndex) { var foundOne = false; var canSkip = false; var previousWasWhitespace = false; var textLine = textSegment as TextLine; var textStyles = new List <TextStyleBase>(textView.GetTextStyles()); string previousStyleType = null; var previousStyleIndex = -1; if (textLine == null) { return(false); } for (var i = index; i <= index + length && i < textSegment.GetLength(textColumnIndex); i++) { #region If whitespace found, enable word-jump-search and only search on first char per word var isWhitespace = i < index + length && Char.IsWhiteSpace(textSegment.GetText(textColumnIndex)[i]); if (canSkip) { if (isWhitespace == false) { if (previousWasWhitespace == false) { continue; } } else { previousWasWhitespace = true; continue; // Don't need to search on a whitespace. } } else if (isWhitespace) { canSkip = true; previousWasWhitespace = true; continue; // Don't need to search on a whitespace. } previousWasWhitespace = false; #endregion ITextSegmentStyled newStyledTextSegment = null; for (var s = 0; s < textStyles.Count; s++) { if (textStyles[s].UpdateOnlyOnFinalizingChange && changeWasFinalizer == false) { continue; } newStyledTextSegment = textStyles[s].FindStyledTextSegment(textView, textSegment, this.TextHandler, i, -1, textColumnIndex); if (newStyledTextSegment != null) { //textStyles.RemoveAt(s); break; } } if (newStyledTextSegment == null) { continue; } var found = false; foreach (var existingStyle in GetAll(textLine, i, newStyledTextSegment.Style.NameKey)) { if (existingStyle.Style.NameKey == newStyledTextSegment.Style.NameKey) { if (newStyledTextSegment.Index == existingStyle.Index && newStyledTextSegment.GetLength(textColumnIndex) == existingStyle.GetLength(textColumnIndex)) { found = true; break; } this.RemoveTextSegment(existingStyle); break; } } if (found == false) { foundOne = true; // TODO: Make this line actually work. (NOTE: what did I mean here? ;D) this.AddManualTextSegment(newStyledTextSegment, textLine.Index + newStyledTextSegment.Index, textColumnIndex); } if (previousStyleType != newStyledTextSegment.Style.NameKey && previousStyleIndex != newStyledTextSegment.Index) { // Decrease it so that we stay on the same location, in case there are several styles overlapping on the same spot. i--; } previousStyleType = newStyledTextSegment.Style.NameKey; previousStyleIndex = newStyledTextSegment.Index; } return(foundOne); }
public unsafe void Render(IntPtr hdc, int vpx, int vpy, Size size) { #region Initialize GDI resources if (this._brushCurrentLine == null) { var colorWithoutTransparency = Color.FromArgb(this.TextView.LineHighlightColor.R, this.TextView.LineHighlightColor.G, this.TextView.LineHighlightColor.B); this._brushCurrentLine = new SafeHandleGDI(SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(colorWithoutTransparency))); } #endregion var styleSelection = this.TextView.GetTextStyle("Selection"); var styleDefault = this.TextView.GetTextStyle("Default"); var rs = new RendererState(this.TextView.GetTextRectangle(false), this.TextView.LineHeight); rs.TextView = this.TextView; rs.RenderState = new RenderState(this.TextView, styleDefault); rs.ViewportX = vpx - rs.TextRectangle.Left; rs.ViewportY = vpy; ITextSegmentStyled selectionSegment = null; ITextSegment firstVisibleLine = null; //var foundActiveLine = this.TextView.LineHighlightColor.A == Color.Transparent.A || this.TextView.LineHighlightColor == Color.Empty; var textColumnIndex = this.TextView.CurrentTextColumnIndex; var sri = new StyleRenderInfo(this.FocusedStyledSegment); // TODO: Paint some nice graphics for the current text column index, when it is stable enough. var clientSize = this.TextView.ClientSize; var lineCount = this.Strategy.Lines.Count; var firstCharIndex = this.TextView.GetFirstCharIndexFromLine(this.TextView.GetCurrentLine()); var lineIndexPhysical = 0; for (rs.LineIndexPhysical = 0; rs.LineIndexPhysical < lineCount; lineIndexPhysical++, rs.LineIndexPhysical++) { if (rs.Y > rs.ViewportY + size.Height) { // This line is after the viewport and does not need painting. break; } rs.Line = this.Strategy.Lines[lineIndexPhysical]; var visualInfo = this.TextView.GetVisualInformation(lineIndexPhysical); var lineCountVisual = visualInfo.GetLineCountVisual(textColumnIndex); var linesHeight = lineCountVisual * rs.LineHeight; if (rs.Y + linesHeight <= rs.ViewportY) { // This line is before the viewport. rs.Y += linesHeight; rs.LineIndexVirtual += lineCountVisual; continue; } if (rs.Line.Index >= firstCharIndex && rs.Line.Index <= (this.TextView.SelectionStart + this.TextView.SelectionLength)) { rs.LineIndexVirtualFocused = rs.LineIndexVirtual; if (this.TextView.SelectionLength == 0) { this.RenderSelectedLineBackground(hdc, rs); } } var textPoints = new Dictionary <int, List <ITextSegmentStyled> >(); if (firstVisibleLine == null) { firstVisibleLine = rs.Line; #region Special handling for selection if (this.TextView.SelectionLength > 0) { if (this.TextView.SelectionStart < rs.Line.Index && this.TextView.SelectionStart + this.TextView.SelectionLength >= rs.Line.Index) { // The selection begins on the line before this. selectionSegment = new TextAnchor(styleSelection); selectionSegment.Index = firstVisibleLine.Index; var textPointIndex = rs.Line.Index; if (textPoints.ContainsKey(textPointIndex) == false) { textPoints.Add(textPointIndex, new List <ITextSegmentStyled>()); } textPoints[textPointIndex].Add(selectionSegment); } } #endregion } var lineLength = rs.Line.GetLength(textColumnIndex); if (this.TextView.SelectionLength > 0) { #region Special handling for selection if (this.TextView.SelectionStart >= rs.Line.Index && this.TextView.SelectionStart <= rs.Line.Index + lineLength) { // The selection begins on this line. selectionSegment = new TextAnchor(styleSelection); selectionSegment.Index = rs.Line.Index; selectionSegment.SetLength(textColumnIndex, this.TextView.SelectionLength); var textPointIndex = this.TextView.SelectionStart; if (textPoints.ContainsKey(textPointIndex) == false) { textPoints.Add(textPointIndex, new List <ITextSegmentStyled>()); } textPoints[textPointIndex].Add(selectionSegment); } if (this.TextView.SelectionStart + this.TextView.SelectionLength >= rs.Line.Index && this.TextView.SelectionStart + this.TextView.SelectionLength <= rs.Line.Index + lineLength) { // The selection ends on this line. var textPointIndex = -(this.TextView.SelectionStart + this.TextView.SelectionLength); if (textPoints.ContainsKey(textPointIndex) == false) { textPoints.Add(textPointIndex, new List <ITextSegmentStyled>()); } textPoints[textPointIndex].Add(selectionSegment); } #endregion } var textLine = (TextLine)rs.Line; if (textLine.StyledTextSegments != null && textLine.StyledTextSegments.Count > 0) { foreach (var textSegment in textLine.StyledTextSegments) { var textPointStartIndex = textLine.Index + textSegment.Index; if (textPoints.ContainsKey(textPointStartIndex) == false) { textPoints.Add(textPointStartIndex, new List <ITextSegmentStyled>()); } textPoints[textPointStartIndex].Add(textSegment); var textPointEndIndex = -(textLine.Index + textSegment.Index + textSegment.GetLength(textColumnIndex)); if (textPoints.ContainsKey(textPointEndIndex) == false) { textPoints.Add(textPointEndIndex, new List <ITextSegmentStyled>()); } textPoints[textPointEndIndex].Add(textSegment); } } var wordWrapIndex = 0; var tabIndex = 0; rs.X = 0; var previousTextIndex = 0; //var textLength = rs.Line.GetLength(textColumnIndex); var lineSplitIndexes = visualInfo.GetLineSplitIndexes(textColumnIndex); for (var textIndex = 0; textIndex <= lineLength; textIndex++) { var isLastIndex = textIndex == lineLength; var isNewline = lineSplitIndexes != null; if (isNewline) { isNewline = wordWrapIndex < lineSplitIndexes.Length && lineSplitIndexes[wordWrapIndex] == textIndex; if (isNewline) { wordWrapIndex++; } } var isTab = visualInfo.GetTabSplitIndexes(textColumnIndex) != null; if (isTab) { isTab = tabIndex < visualInfo.GetTabSplitIndexes(textColumnIndex).Length&& visualInfo.GetTabSplitIndexes(textColumnIndex)[tabIndex] == textIndex; if (isTab) { tabIndex++; } } var globalIndex = rs.Line.Index + textIndex; var styleStart = textPoints.ContainsKey(globalIndex) ? textPoints[globalIndex] : null; var styleEnd = globalIndex != 0 && textPoints.ContainsKey(-globalIndex) ? textPoints[-globalIndex] : null; if ((isLastIndex || isNewline || isTab || styleStart != null || styleEnd != null) == false) { // This is a regular character, and no change is done for it. continue; } var start = previousTextIndex; var length = textIndex - start; var outputText = rs.Line.GetText(textColumnIndex); #region Add empty space at end of text if selection goes beyond current line if (start + length == lineLength) { foreach (var rsi in rs.RenderState.GetRenderStateItems()) { if (rsi.Segment.Style.NameKey != styleSelection.NameKey) { continue; } if (styleEnd != null) { var isStyleSelection = false; foreach (var se in styleEnd) { if (se.Style.NameKey == styleSelection.NameKey) { isStyleSelection = true; break; } } if (isStyleSelection) { break; } } outputText += " "; length++; break; } } #endregion fixed(char *c = outputText) { SafeNativeMethods.TextOut(hdc, rs.TextRectangle.Left + (rs.X - rs.ViewportX), rs.TextRectangle.Top + rs.Y - rs.ViewportY, c + start, length); if ((isNewline == false && isLastIndex == false) || styleEnd != null) { rs.X += rs.Line.GetSize(hdc, rs.X, start, length, visualInfo.GetVisualInfo(textColumnIndex)).Width; } if (styleEnd != null) { foreach (var t in styleEnd) { switch (t.Style.PaintMode) { case TextStylePaintMode.Custom: { t.Style.Paint(hdc, t, this.TextView, visualInfo.GetVisualInfo(textColumnIndex), rs.TextRectangle.Left + (rs.X - rs.ViewportX), rs.TextRectangle.Top + rs.Y - rs.ViewportY, rs.LineHeight, sri); } break; } } } } if (isNewline) { this.RenderLineColumns(hdc, clientSize, rs); rs.X = 0; rs.LineIndexVirtual++; rs.Y += rs.LineHeight; } if (styleStart != null) { foreach (var t in styleStart) { rs.RenderState.Add(this.TextView, t); } rs.RenderState.Apply(hdc); } if (styleEnd != null) { foreach (var t in styleEnd) { rs.RenderState.Remove(t); } rs.RenderState.Apply(hdc); } previousTextIndex = textIndex; } if (this.TextView.WordWrapGlyphs && lineCountVisual > 1) { RenderWordWrapGlyph(hdc, rs.ViewportY, rs.Y, rs.TextRectangle, rs.LineHeight); } this.RenderLineColumns(hdc, clientSize, rs); rs.X = 0; rs.LineIndexVirtual++; rs.Y += rs.LineHeight; } this.PaintTooltipOverlay(hdc); }
/// <summary> /// /// </summary> /// <param name="textView"></param> /// <param name="textLine"></param> /// <param name="relativeIndex">Relative index is the index before the new character, so text[relativeIndex] is the <see cref="c"/>.</param> /// <param name="c"></param> /// <param name="alterTextStyleIndexes"></param> /// <param name="length"></param> /// <param name="textColumnIndex"></param> private void ModifyStyledTextSegments(ITextView textView, TextLine textLine, int relativeIndex, char c, bool alterTextStyleIndexes, int length, int textColumnIndex) { var isErase = c == '\0' && length <= 0; if (isErase) { length *= -1; } IEnumerable <ITextSegmentStyled> befores = null; IEnumerable <ITextSegmentStyled> afters = null; var startSearch = Math.Max(0, relativeIndex - 1); const bool foundMatch = false; if (alterTextStyleIndexes) { var offsetCount = 0; for (var n = 0; n < textLine.StyledTextSegments.Count - offsetCount; n++) { if (textLine.StyledTextSegments[n].Index > textLine.GetLength(textColumnIndex)) { // The style starts after the end of the line, which is silly and should be filtered out. textLine.StyledTextSegments[n].TextLine = null; n--; } else if (isErase && textLine.StyledTextSegments[n].Style.Type == TextStyleType.Automatic && textLine.StyledTextSegments[n].Index >= relativeIndex && textLine.StyledTextSegments[n].Index + textLine.StyledTextSegments[n].GetLength(textColumnIndex) <= relativeIndex + length) { // The whole styled text segment was inside the removed range of text. // It does not exist anymore and is automatically eligible for removing. textLine.StyledTextSegments[n].TextLine = null; n--; } else if (textLine.StyledTextSegments[n].Style.Type == TextStyleType.Automatic && textLine.StyledTextSegments[n].Contains(relativeIndex, length, isErase, true)) { if (befores == null) { // This will search from the character before the change, the character before a new addition, // or the character before the character that was removed. befores = this.FindStyles(textView, textLine, startSearch, textColumnIndex); // If a new addition, we search from the character after the change (so "pol<new space>ice" will search on "i" and not <new space>). // When removing we only need to search from where the removal took place. var afterSearchIdx = isErase == false?Math.Min(textLine.GetLength(textColumnIndex), startSearch + 2) : startSearch + 1; afters = this.FindStyles(textView, textLine, afterSearchIdx, textColumnIndex); } var current = textLine.StyledTextSegments[n]; if (befores != null || afters != null) { ITextSegmentStyled before = null; ITextSegmentStyled after = null; if (befores != null) { foreach (var b in befores) { if (b.Style.NameKey == current.Style.NameKey) { before = b; break; } } } if (afters != null) { foreach (var a in afters) { if (a.Style.NameKey == current.Style.NameKey) { after = a; break; } } } if (before == null) { if (after == null) { // The styled text segment is no more since it is no longer found. current.TextLine = null; n--; continue; } before = after; after = null; } else if (after != null && before.Object != null && before.Object.Equals(after.Object)) { after = null; } if (before.Index == current.Index && before.GetLength(textColumnIndex) == current.GetLength(textColumnIndex) && ((before.Object != null && before.Object.Equals(current.Object)) || before.Object == null && current.Object == null)) { continue; // No change was done. Just don't do any changes. } //foundMatch = true; if (before.Contains(current.Index, current.GetLength(textColumnIndex), true, true)) { current.TextLine = null; n--; } ((TextAnchor)before).TextLine = textLine; offsetCount++; if (after != null) { ((TextAnchor)after).TextLine = textLine; offsetCount++; } } else { // The styled text segment is no more since it is no longer found. current.TextLine = null; n--; } } else if (textLine.StyledTextSegments[n].Index > relativeIndex) { if (isErase) { textLine.StyledTextSegments[n].Index -= length; } else { textLine.StyledTextSegments[n].Index += length; } } } } if (foundMatch == false) { #if DEBUG var foundOne = #endif this.TextSegmentStyledManager.SearchAndApplyTo(textView, textLine, startSearch, 1, CharacterIsFinalizer(c), textColumnIndex); } }
public StyleRenderInfo(ITextSegmentStyled selectedSegmentStyled) { this.SelectedTextSegment = selectedSegmentStyled; }