📄 jedittextarea.java
字号:
* @param doElectricScroll If true, electric scrolling will be performed */ public void scrollToCaret(boolean doElectricScroll) { scrollTo(caretLine,caret - buffer.getLineStartOffset(caretLine), doElectricScroll); } //}}} //{{{ scrollTo() method /** * Ensures that the specified location in the buffer is visible. * @param line The line number * @param offset The offset from the start of the line * @param doElectricScroll If true, electric scrolling will be performed * @since jEdit 4.0pre6 */ public void scrollTo(int line, int offset, boolean doElectricScroll) { int extraEndVirt; int lineLength = buffer.getLineLength(line); if(offset > lineLength) { extraEndVirt = charWidth * (offset - lineLength); offset = lineLength; } else extraEndVirt = 0; int _electricScroll = (doElectricScroll && visibleLines > electricScroll * 2 ? electricScroll : 0); // visibleLines == 0 before the component is realized // we can't do any proper scrolling then, so we have // this hack... if(visibleLines == 0) { setFirstLine(physicalToVirtual( Math.max(0,line - _electricScroll))); return; } //{{{ STAGE 1 -- determine if the caret is visible. int screenLine = getScreenLineOfOffset(buffer.getLineStartOffset(line) + offset); Point point; if(screenLine != -1) { // It's visible, but is it too close to the borders? int height = painter.getFontMetrics().getHeight(); int y1 = (firstLine == 0 ? 0 : height * _electricScroll); int y2 = (visibleLines + firstLine == getVirtualLineCount() ? 0 : height * _electricScroll); Rectangle rect = new Rectangle(0,y1, painter.getWidth() - 5,visibleLines * height - y1 - y2); point = offsetToXY(line,offset,returnValue); point.x += extraEndVirt; if(rect.contains(point)) return; } else point = null; //}}} //{{{ STAGE 2 -- scroll vertically if(line == physLastLine + 1) { int count = chunkCache.getLineInfosForPhysicalLine(physLastLine).length + chunkCache.getLineInfosForPhysicalLine(physLastLine + 1).length + _electricScroll; while(count > 0) { count -= chunkCache.getLineInfosForPhysicalLine(physFirstLine).length; firstLine++; physFirstLine = foldVisibilityManager.getNextVisibleLine(physFirstLine); } } else if(screenLine == -1) { if(line == physLastLine) { int count = chunkCache.getLineInfosForPhysicalLine(physLastLine).length + _electricScroll; while(count > 0) { count -= chunkCache.getLineInfosForPhysicalLine(physFirstLine).length; firstLine++; int nextLine = foldVisibilityManager.getNextVisibleLine(physFirstLine); if(nextLine == -1) break; else physFirstLine = nextLine; } } int virtualLine = foldVisibilityManager.physicalToVirtual(line); if(virtualLine == firstLine - 1) { firstLine = Math.max(0,firstLine - _electricScroll - 1); physFirstLine = foldVisibilityManager.virtualToPhysical(firstLine); } else { // keep chunking lines until we have visibleLines / 2 if(!softWrap && virtualLine >= foldVisibilityManager.getVirtualLineCount() - visibleLines / 2) { firstLine = foldVisibilityManager.getVirtualLineCount() - visibleLines; physFirstLine = foldVisibilityManager .virtualToPhysical(firstLine); } else { physFirstLine = line; int count = 0; for(;;) { if(foldVisibilityManager.isLineVisible(physFirstLine)) { int incr = chunkCache.getLineInfosForPhysicalLine(physFirstLine).length; if(count + incr > visibleLines / 2) break; else count += incr; } int prevLine = foldVisibilityManager .getPrevVisibleLine(physFirstLine); if(prevLine == -1) break; else physFirstLine = prevLine; } firstLine = physicalToVirtual(physFirstLine); } } } else if(screenLine < _electricScroll && firstLine != 0) { int count = _electricScroll - screenLine; while(count > 0 && firstLine > 0) { count -= chunkCache.getLineInfosForPhysicalLine(physFirstLine).length; firstLine--; physFirstLine = foldVisibilityManager.getPrevVisibleLine(physFirstLine); } } else if(screenLine >= visibleLines - _electricScroll) { int count = _electricScroll - visibleLines + screenLine + 1; while(count > 0 && firstLine <= getVirtualLineCount()) { count -= chunkCache.getLineInfosForPhysicalLine(physFirstLine).length; firstLine++; physFirstLine = foldVisibilityManager.getNextVisibleLine(physFirstLine); } } chunkCache.setFirstLine(firstLine,physFirstLine,false); recalculateLastPhysicalLine(); if(point == null) { point = offsetToXY(line,offset,returnValue); if(point == null) { // a soft wrapped line has more screen lines // than the number of visible lines return; } else point.x += extraEndVirt; } //}}} //{{{ STAGE 3 -- scroll horizontally if(point.x < 0) { horizontalOffset = Math.min(0,horizontalOffset - point.x + charWidth + 5); } else if(point.x >= painter.getWidth() - charWidth - 5) { horizontalOffset = horizontalOffset + (painter.getWidth() - point.x) - charWidth - 5; } //}}} //{{{ STAGE 4 -- update some stuff updateScrollBars(); painter.repaint(); gutter.repaint(); view.synchroScrollVertical(this,firstLine); view.synchroScrollHorizontal(this,horizontalOffset); // fire events for both a horizontal and vertical scroll fireScrollEvent(true); fireScrollEvent(false); //}}} } //}}} //{{{ addScrollListener() method /** * Adds a scroll listener to this text area. * @param listener The listener * @since jEdit 3.2pre2 */ public final void addScrollListener(ScrollListener listener) { listenerList.add(ScrollListener.class,listener); } //}}} //{{{ removeScrollListener() method /** * Removes a scroll listener from this text area. * @param listener The listener * @since jEdit 3.2pre2 */ public final void removeScrollListener(ScrollListener listener) { listenerList.remove(ScrollListener.class,listener); } //}}} //}}} //{{{ Screen line stuff //{{{ getPhysicalLineOfScreenLine() method /** * Returns the physical line number that contains the specified screen * line. * @param screenLine The screen line * @since jEdit 4.0pre6 */ public int getPhysicalLineOfScreenLine(int screenLine) { chunkCache.updateChunksUpTo(screenLine); return chunkCache.getLineInfo(screenLine).physicalLine; } //}}} //{{{ getScreenLineOfOffset() method /** * Returns the screen (wrapped) line containing the specified offset. * @param offset The offset * @since jEdit 4.0pre4 */ public int getScreenLineOfOffset(int offset) { int line = buffer.getLineOfOffset(offset); offset -= buffer.getLineStartOffset(line); return chunkCache.getScreenLineOfOffset(line,offset); } //}}} //{{{ getScreenLineStartOffset() method /** * Returns the start offset of the specified screen (wrapped) line. * @param line The line * @since jEdit 4.0pre4 */ public int getScreenLineStartOffset(int line) { chunkCache.updateChunksUpTo(line); ChunkCache.LineInfo lineInfo = chunkCache.getLineInfo(line); if(lineInfo.physicalLine == -1) return -1; return buffer.getLineStartOffset(lineInfo.physicalLine) + lineInfo.offset; } //}}} //{{{ getScreenLineEndOffset() method /** * Returns the end offset of the specified screen (wrapped) line. * @param line The line * @since jEdit 4.0pre4 */ public int getScreenLineEndOffset(int line) { chunkCache.updateChunksUpTo(line); ChunkCache.LineInfo lineInfo = chunkCache.getLineInfo(line); if(lineInfo.physicalLine == -1) return -1; return buffer.getLineStartOffset(lineInfo.physicalLine) + lineInfo.offset + lineInfo.length; } //}}} //}}} //{{{ Offset conversion //{{{ xyToOffset() method /** * Converts a point to an offset. * Note that unlike in previous jEdit versions, this method now returns * -1 if the y co-ordinate is out of bounds. * * @param x The x co-ordinate of the point * @param y The y co-ordinate of the point */ public int xyToOffset(int x, int y) { return xyToOffset(x,y,true); } //}}} //{{{ xyToOffset() method /** * Converts a point to an offset. * Note that unlike in previous jEdit versions, this method now returns * -1 if the y co-ordinate is out of bounds. * * @param x The x co-ordinate of the point * @param y The y co-ordinate of the point * @param round Round up to next letter if past the middle of a letter? * @since jEdit 3.2pre6 */ public int xyToOffset(int x, int y, boolean round) { FontMetrics fm = painter.getFontMetrics(); int height = fm.getHeight(); int line = y / height; if(line < 0 || line > visibleLines) return -1; chunkCache.updateChunksUpTo(line); ChunkCache.LineInfo lineInfo = chunkCache.getLineInfo(line); if(!lineInfo.chunksValid) System.err.println("xy to offset: not valid"); if(lineInfo.physicalLine == -1) { return getLineEndOffset(foldVisibilityManager .getLastVisibleLine()) - 1; } else { int offset = Chunk.xToOffset(lineInfo.chunks, x - horizontalOffset,round); if(offset == -1 || offset == lineInfo.offset + lineInfo.length) offset = lineInfo.offset + lineInfo.length - 1; return getLineStartOffset(lineInfo.physicalLine) + offset; } } //}}} //{{{ offsetToXY() method /** * Converts an offset into a point in the text area painter's * co-ordinate space. * @param offset The offset * @return The location of the offset on screen, or <code>null</code> * if the specified offset is not visible */ public Point offsetToXY(int offset) { int line = buffer.getLineOfOffset(offset); offset -= buffer.getLineStartOffset(line); Point retVal = new Point(); return offsetToXY(line,offset,retVal); } //}}} //{{{ offsetToXY() method /** * Converts an offset into a point in the text area painter's * co-ordinate space. * @param line The physical line number * @param offset The offset, from the start of the line * @param retVal The point to store the return value in * @return <code>retVal</code> for convenience, or <code>null</code> * if the specified offset is not visible * @since jEdit 4.0pre4 */ public Point offsetToXY(int line, int offset, Point retVal) { int screenLine = chunkCache.getScreenLineOfOffset(line,offset); if(screenLine == -1) { if(line < physFirstLine) return null; // must have >= here because the last physical line // might only be partially visible (some offsets would // have a screen line, others would return -1 and hence // this code would be executed) else if(line >= physLastLine) return null; else { throw new InternalError("line=" + line + ",offset=" + offset + ",screenLine=" + screenLine + ",physFirstLine=" + physFirstLine + ",physLastLine=" + physLastLine); } } FontMetrics fm = painter.getFontMetrics(); retVal.y = screenLine * fm.getHeight(); chunkCache.updateChunksUpTo(screenLine); ChunkCache.LineInfo info = chunkCache.getLineInfo(screenLine); if(!info.chunksValid) System.err.println("offset to xy: not valid"); retVal.x = (int)(horizontalOffset + Chunk.offsetToX( info.chunks,offset)); return retVal; } //}}} //}}} //{{{ Painting //{{{ invalidateScreenLineRange() method /** * Marks a range of screen lines as needing a repaint. * @param start The first line * @param end The last line * @since jEdit 4.0pre4 */ public void invalidateScreenLineRange(int start, int end) { //if(start != end) // System.err.println(start + ":" + end + ":" + chunkCache.needFullRepaint()); if(chunkCache.needFullRepaint()) { recalculateLastPhysicalLine(); gutter.repaint(); painter.repaint(); return; } if(start > end) { int tmp = end; end = start; start = tmp; } FontMetrics fm = painter.getFontMetrics(); int y = start * fm.getHeight(); int height = (end - start + 1) * fm.getHeight(); painter.repaint(0,y,painter.getWidth(),height); gutter.repaint(0,y,gutter.getWidth(),height); } //}}} //{{{ invalidateLine() method /** * Marks a line as needing a repaint. * @param line The physical line to invalidate */ public void invalidateLine(int line) { if(line < physFirstLine || line > physLastLine || !foldVisibilityManager.isLineVisible(line)) return; int startLine = -1; int endLine = -1; for(int i = 0; i <= visibleLines; i++) { chunkCache.updateChunksUpTo(i); ChunkCache.LineInfo info = chunkCache.getLineInfo(i); if((info.physicalLine >= line || info.physicalLine == -1) && startLine == -1) { startLine = i; } if((info.physicalLine >= line && info.lastSubregion) || info.physicalLine == -1) { endLine = i; break; } } if(chunkCache.needFullRepaint()) { recalculateLastPhysicalLine(); endLine = visibleLines; } else if(endLine == -1) endLine = visibleLines; //if(startLine != endLine) // System.err.println(startLine + ":" + endLine); invalidateScreenLineRange(startLine,endLine); } //}}} //{{{ invalidateLineRange() method /** * Marks a range of physical lines as needing a repaint. * @param start The first line to invalidate * @param end The last line to invalidate */ public void invalidateLineRange(int start, int end) { if(end < start) { int tmp = end; end = start; start = tmp; } if(end < physFirstLine || start > physLastLine) return; int startScreenLine = -1; int endScreenLine = -1; for(int i = 0; i <= visibleLines; i++) { chunkCache.updateChunksUpTo(i); ChunkCache.LineInfo info = chunkCache.getLineInfo(i); if((info.physicalLine >= start || info.physicalLine == -1) && startScreenLine == -1) { startScreenLine = i; } if((info.physicalLine >= end && info.lastSubregion) || info.physicalLine == -1) { endScreenLine = i; break; } } if(startScreenLine == -1) startScreenLine = 0; if(chunkCache.needFullRepaint()) { recalculateLastPhysicalLine(); endScreenLine = visibleLines; } else if(endScreenLine == -1) endScreenLine = visibleLines; invalidateScreenLineRange(startScreenLine,endScreenLine); } //}}} //{{{ invalidateSelectedLines() method /** * Repaints the lines containing the selection. */ public void invalidateSelectedLines() { // to hide line highlight if selections are being added later on invalidateLine(caretLine); for(int i = 0; i < selection.size(); i++) { Selection s = (Selection)selection.elementAt(i); invalidateLineRange(s.startLine,s.endLine); } } //}}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -