private synchronized void adjustOther(StyledText source, StyledText other) { if (source == null) source = this.source; if (other == null) other = this.other; if (source == null) { logWriter.println("WARNING: attempting to adjust source but no source StyledText"); return; } if (other == null) { logWriter.println("WARNING: attempting to adjust other but no other StyledText"); return; } int caretOffset = source.getCaretOffset(); int lineIndex = source.getLineAtOffset(caretOffset); int otherLineHeight = other.getLineHeight(); int otherLineRealPixel = lineIndex * otherLineHeight; int sourceLinePixel = source.getLinePixel(lineIndex); int otherTopPixel = otherLineRealPixel - sourceLinePixel; int otherHeight = other.getClientArea().height; int otherLineBelow = otherHeight - (sourceLinePixel + otherLineHeight); int otherLineCount = other.getLineCount(); int otherLinesBelow = otherLineCount - lineIndex; int otherLinesBelowHeight = otherLinesBelow * otherLineHeight; int otherBottomGap = otherHeight - (sourceLinePixel + otherLinesBelowHeight); // other would have to scroll before first line if (otherTopPixel < 0) { int sourceTopPixel = source.getTopPixel() - otherTopPixel; otherTopPixel = 0; source.setTopPixel(sourceTopPixel); } // other line would be partially past the bottom of view else if (otherLineBelow < 0) { int sourceTopPixel = source.getTopPixel() - otherLineBelow; otherTopPixel -= otherLineBelow; source.setTopPixel(sourceTopPixel); } // other would have to scroll past last line else if (otherBottomGap > 0) { int sourceTopPixel = source.getTopPixel() - otherBottomGap; otherTopPixel -= otherBottomGap; source.setTopPixel(sourceTopPixel); } other.setTopPixel(otherTopPixel); redraw(); }
/** * Scrolls the containing editor to the given offset of the contained editor * * @param editor * @param scrollTo text offset in the embedded editor that should be revealed */ public void revealSelection(ContainedEditorManager editor, int scrollTo) { StyledText containedStyledText = (StyledText) editor.getAdapter(StyledText.class); // this progression determines the location of the offset in the coordinate system // of the containing styledText Point containedLoc = containedStyledText.getLocationAtOffset(scrollTo); Point displayLoc = containedStyledText.toDisplay(containedLoc); Point containingLoc = styledText.toControl(displayLoc); // next, we determine if this location is in the visible area. Point containingSize = styledText.getSize(); Rectangle containingBounds = new Rectangle(0, 0, containingSize.x, containingSize.y); if (!containingBounds.contains(containingLoc)) { // pad a little to the left and a little bit down containingLoc.x -= 50; containingLoc.y += 100; // if not, then perform a scroll. styledText.setTopPixel(styledText.getTopPixel() + containingLoc.y - containingSize.y); // do the same for horizontal styledText.setHorizontalPixel(styledText.getHorizontalPixel() + containingLoc.x); } paint(ContainingEditor.EMBEDDED_REPAINT); }
/** * Convert mouse screen coordinates to a <code>StyledText</code> offset. * * @param x screen X-coordinate * @param y screen Y-coordinate * @param absolute if <code>true</code>, coordinates are expected to be absolute screen * coordinates * @return text offset * @see StyledText#getOffsetAtLocation() */ private int getOffsetAtLocation(int x, int y, boolean absolute) { StyledText textWidget = fViewer.getTextWidget(); StyledTextContent content = textWidget.getContent(); Point location; if (absolute) { location = textWidget.toControl(x, y); } else { location = new Point(x, y); } int line = (textWidget.getTopPixel() + location.y) / textWidget.getLineHeight(); if (line >= content.getLineCount()) { return content.getCharCount(); } int lineOffset = content.getOffsetAtLine(line); String lineText = content.getLine(line); Point endOfLine = textWidget.getLocationAtOffset(lineOffset + lineText.length()); if (location.x >= endOfLine.x) { return lineOffset + lineText.length(); } try { return textWidget.getOffsetAtLocation(location); } catch (IllegalArgumentException iae) { // we are expecting this return -1; } }
public int getVerticalScrollOffset() { StyledText st = getSourceViewer().getTextWidget(); int lineHeight = st.getLineHeight(); return getSourceViewer().getTopInset() - ((getDocumentRegionOffset() * lineHeight) + st.getTopPixel()); }
@Override public void paintControl(PaintEvent e) { if (inDraw || styledText == null || styledText.isDisposed()) { return; } try { inDraw = true; boolean showIndentGuide = this.indentGuide.getShowIndentGuide(); if (!showIndentGuide) { return; } int xOffset = styledText.getHorizontalPixel(); int yOffset = styledText.getTopPixel(); // Important: call all to cache the new values (instead of doing all inside the or below). boolean styledTextContentChanged = getStyledTextContentChangedAndStoreNew(); boolean clientAreaChanged = getClientAreaChangedAndStoreNew(); boolean charCountChanged = getCharCountChangedAndStoreNew(); boolean tabWidthChanged = getTabWidthChangedAndStoreNew(); boolean redrawAll = styledTextContentChanged || clientAreaChanged || charCountChanged || tabWidthChanged || xOffset != lastXOffset || yOffset != lastYOffset; StyledTextContent currentContent = this.content; if (currClientArea == null || currClientArea.width < 5 || currClientArea.height < 5 || currCharCount < 1 || currentContent == null || currTabWidth <= 0) { return; } lastXOffset = xOffset; lastYOffset = yOffset; int topIndex; try { topIndex = JFaceTextUtil.getPartialTopIndex(styledText); } catch (IllegalArgumentException e1) { // Just silence it... // java.lang.IllegalArgumentException: Index out of bounds // at org.eclipse.swt.SWT.error(SWT.java:4458) // at org.eclipse.swt.SWT.error(SWT.java:4392) // at org.eclipse.swt.SWT.error(SWT.java:4363) // at org.eclipse.swt.custom.StyledText.getOffsetAtLine(StyledText.java:4405) // at org.eclipse.jface.text.JFaceTextUtil.getPartialTopIndex(JFaceTextUtil.java:103) // at // org.python.pydev.shared_ui.editor.VerticalIndentGuidesPainter.paintControl(VerticalIndentGuidesPainter.java:93) return; } int bottomIndex = JFaceTextUtil.getPartialBottomIndex(styledText); if (redrawAll) { this.lineToVerticalLinesToDraw = this.indentGuide.computeVerticalLinesToDrawInRegion(styledText, topIndex, bottomIndex); // This is a bit unfortunate: when something changes, we may have to repaint out of the // clipping // region, but even setting the clipping region (e.gc.setClipping), the clipping region may // still // be unchanged (because the system said that it only wants to repaint some specific area // already // and we can't make it bigger -- so, what's left for us is asking for a repaint of the full // area // in this case). if (askFullRedraw) { askFullRedraw = false; if (Math.abs(currClientArea.height - e.gc.getClipping().height) > 40) { // Only do it if the difference is really high (some decorations make it usually a bit // lower than // the actual client area -- usually around 14 in my tests, but make it a bit higher as // the usual // difference when a redraw is needed is pretty high). RunInUiThread.async( new Runnable() { @Override public void run() { StyledText s = styledText; if (s != null && !s.isDisposed()) { s.redraw(); } } }); } else { } } } if (this.lineToVerticalLinesToDraw != null) { try (AutoCloseable temp = configGC(e.gc)) { Collection<List<VerticalLinesToDraw>> values = lineToVerticalLinesToDraw.values(); for (List<VerticalLinesToDraw> list : values) { for (VerticalLinesToDraw verticalLinesToDraw : list) { verticalLinesToDraw.drawLine(e.gc); } } } } } catch (Exception e1) { Log.log(e1); } finally { inDraw = false; } }