📄 displaymanager.java
字号:
/* * DisplayManager.java - Low-level text display * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 2001, 2003 Slava Pestov * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */package org.gjt.sp.jedit.textarea;//{{{ Importsimport java.awt.Toolkit;import java.util.*;import org.gjt.sp.jedit.buffer.*;import org.gjt.sp.jedit.*;import org.gjt.sp.util.Log;//}}}/** * Manages low-level text display tasks. * @since jEdit 4.2pre1 * @author Slava Pestov * @version $Id: DisplayManager.java,v 1.85 2004/02/23 05:50:12 spestov Exp $ */public class DisplayManager{ //{{{ Static part public static long scanCount, scannedLines; //{{{ getDisplayManager() method static DisplayManager getDisplayManager(Buffer buffer, JEditTextArea textArea) { List l = (List)bufferMap.get(buffer); DisplayManager dmgr; if(l == null) { l = new LinkedList(); bufferMap.put(buffer,l); } Iterator liter = l.iterator(); while(liter.hasNext()) { dmgr = (DisplayManager)liter.next(); if(!dmgr.inUse && dmgr.textArea == textArea) { dmgr.inUse = true; return dmgr; } } // if we got here, no unused display manager in list dmgr = new DisplayManager(buffer,textArea); dmgr.inUse = true; l.add(dmgr); return dmgr; } //}}} //{{{ releaseDisplayManager() method static void releaseDisplayManager(DisplayManager dmgr) { dmgr.inUse = false; } //}}} //{{{ bufferClosed() method public static void bufferClosed(Buffer buffer) { bufferMap.remove(buffer); } //}}} //{{{ textAreaDisposed() method static void textAreaDisposed(JEditTextArea textArea) { Iterator biter = bufferMap.values().iterator(); while(biter.hasNext()) { List l = (List)biter.next(); Iterator liter = l.iterator(); while(liter.hasNext()) { DisplayManager dmgr = (DisplayManager) liter.next(); if(dmgr.textArea == textArea) { dmgr.dispose(); liter.remove(); } } } } //}}} //{{{ _notifyScreenLineChanges() method /* static void _notifyScreenLineChanges(Buffer buffer) { Iterator iter = ((List)bufferMap.get(buffer)).iterator(); while(iter.hasNext()) { ((DisplayManager)iter.next())._notifyScreenLineChanges(); } } */ //}}} private static Map bufferMap = new HashMap(); //}}} //{{{ isLineVisible() method /** * Returns if the specified line is visible. * @param line A physical line index * @since jEdit 4.2pre1 */ public final boolean isLineVisible(int line) { return fvmget(line) % 2 == 0; } //}}} //{{{ getFirstVisibleLine() method /** * Returns the physical line number of the first visible line. * @since jEdit 4.2pre1 */ public int getFirstVisibleLine() { return fvm[0]; } //}}} //{{{ getLastVisibleLine() method /** * Returns the physical line number of the last visible line. * @since jEdit 4.2pre1 */ public int getLastVisibleLine() { return fvm[fvmcount - 1] - 1; } //}}} //{{{ getNextVisibleLine() method /** * Returns the next visible line after the specified line index. * @param line A physical line index * @since jEdit 4.0pre1 */ public int getNextVisibleLine(int line) { int index = fvmget(line); /* in collapsed range */ if(index % 2 != 0) { /* beyond last visible line */ if(fvmcount == index + 1) return - 1; /* start of next expanded range */ else return fvm[index + 1]; } /* last in expanded range */ else if(line == fvm[index + 1] - 1) { /* equal to last visible line */ if(fvmcount == index + 2) return -1; /* start of next expanded range */ else return fvm[index + 2]; } /* next in expanded range */ else return line + 1; } //}}} //{{{ getPrevVisibleLine() method /** * Returns the previous visible line before the specified line index. * @param line A physical line index * @since jEdit 4.0pre1 */ public int getPrevVisibleLine(int line) { int index = fvmget(line); /* before first visible line */ if(index == -1) return -1; /* in collapsed range */ else if(index % 2 == 1) { /* end of prev expanded range */ return fvm[index] - 1; } /* first in expanded range */ else if(line == fvm[index]) { /* equal to first visible line */ if(index == 0) return -1; /* end of prev expanded range */ else return fvm[index - 1] - 1; } /* prev in expanded range */ else return line - 1; } //}}} //{{{ getScreenLineCount() method public final int getScreenLineCount(int line) { if(lineMgr.isScreenLineCountValid(line)) return lineMgr.getScreenLineCount(line); else { int newCount = textArea.chunkCache .getLineSubregionCount(line); setScreenLineCount(line,newCount); return newCount; } } //}}} //{{{ getScrollLineCount() method public final int getScrollLineCount() { return scrollLineCount.scrollLine; } //}}} //{{{ collapseFold() method /** * Collapses the fold at the specified physical line index. * @param line A physical line index * @since jEdit 4.2pre1 */ public void collapseFold(int line) { int lineCount = buffer.getLineCount(); int start = 0; int end = lineCount - 1; // if the caret is on a collapsed fold, collapse the // parent fold if(line != 0 && line != buffer.getLineCount() - 1 && buffer.isFoldStart(line) && !isLineVisible(line + 1)) { line--; } int initialFoldLevel = buffer.getFoldLevel(line); //{{{ Find fold start and end... if(line != lineCount - 1 && buffer.getFoldLevel(line + 1) > initialFoldLevel) { // this line is the start of a fold start = line + 1; for(int i = line + 1; i < lineCount; i++) { if(buffer.getFoldLevel(i) <= initialFoldLevel) { end = i - 1; break; } } } else { boolean ok = false; // scan backwards looking for the start for(int i = line - 1; i >= 0; i--) { if(buffer.getFoldLevel(i) < initialFoldLevel) { start = i + 1; ok = true; break; } } if(!ok) { // no folds in buffer return; } for(int i = line + 1; i < lineCount; i++) { if(buffer.getFoldLevel(i) < initialFoldLevel) { end = i - 1; break; } } } //}}} // Collapse the fold... hideLineRange(start,end); _notifyScreenLineChanges(); textArea.foldStructureChanged(); } //}}} //{{{ expandFold() method /** * Expands the fold at the specified physical line index. * @param line A physical line index * @param fully If true, all subfolds will also be expanded * @since jEdit 4.2pre1 */ public int expandFold(int line, boolean fully) { // the first sub-fold. used by JEditTextArea.expandFold(). int returnValue = -1; int lineCount = buffer.getLineCount(); int start = 0; int end = lineCount - 1; int initialFoldLevel = buffer.getFoldLevel(line); //{{{ Find fold start and fold end... if(line != lineCount - 1 && isLineVisible(line) && !isLineVisible(line + 1) && buffer.getFoldLevel(line + 1) > initialFoldLevel) { // this line is the start of a fold int index = fvmget(line + 1); if(index == -1) { expandAllFolds(); return -1; } start = fvm[index]; if(index != fvmcount - 1) end = fvm[index + 1] - 1; else { start = line + 1; for(int i = line + 1; i < lineCount; i++) { if(/* isLineVisible(i) && */ buffer.getFoldLevel(i) <= initialFoldLevel) { end = i - 1; break; } } } } else { int index = fvmget(line); if(index == -1) { expandAllFolds(); return -1; } start = fvm[index]; if(index != fvmcount - 1) end = fvm[index + 1] - 1; else { for(int i = line + 1; i < lineCount; i++) { //XXX if((isLineVisible(i) && buffer.getFoldLevel(i) < initialFoldLevel) || i == getLastVisibleLine()) { end = i - 1; break; } } } } //}}} //{{{ Expand the fold... if(fully) { showLineRange(start,end); } else { // we need a different value of initialFoldLevel here! initialFoldLevel = buffer.getFoldLevel(start); int firstVisible = start; for(int i = start; i <= end; i++) { if(buffer.getFoldLevel(i) > initialFoldLevel) { if(returnValue == -1 && i != 0 && buffer.isFoldStart(i - 1)) { returnValue = i - 1; } if(firstVisible != i) { showLineRange(firstVisible,i - 1); } firstVisible = i + 1; } } if(firstVisible != end + 1) showLineRange(firstVisible,end); if(!isLineVisible(line)) { // this is a hack, and really needs to be done better. expandFold(line,false); return returnValue; } } //}}} _notifyScreenLineChanges(); textArea.foldStructureChanged(); return returnValue; } //}}} //{{{ expandAllFolds() method /** * Expands all folds. * @since jEdit 4.2pre1 */ public void expandAllFolds() { showLineRange(0,buffer.getLineCount() - 1); _notifyScreenLineChanges(); textArea.foldStructureChanged(); } //}}} //{{{ expandFolds() method /** * This method should only be called from <code>actions.xml</code>. * @since jEdit 4.2pre1 */ public void expandFolds(char digit) { if(digit < '1' || digit > '9') { Toolkit.getDefaultToolkit().beep(); return; } else expandFolds((int)(digit - '1') + 1); } //}}} //{{{ expandFolds() method /** * Expands all folds with the specified fold level. * @param foldLevel The fold level * @since jEdit 4.2pre1 */ public void expandFolds(int foldLevel) { if(buffer.getFoldHandler() instanceof IndentFoldHandler) foldLevel = (foldLevel - 1) * buffer.getIndentSize() + 1; showLineRange(0,buffer.getLineCount() - 1); /* this ensures that the first line is always visible */ boolean seenVisibleLine = false; int firstInvisible = 0; for(int i = 0; i < buffer.getLineCount(); i++) { if(!seenVisibleLine || buffer.getFoldLevel(i) < foldLevel) { if(firstInvisible != i) { hideLineRange(firstInvisible, i - 1); } firstInvisible = i + 1; seenVisibleLine = true; } } if(firstInvisible != buffer.getLineCount()) hideLineRange(firstInvisible,buffer.getLineCount() - 1); _notifyScreenLineChanges(); textArea.foldStructureChanged(); } //}}} //{{{ narrow() method /** * Narrows the visible portion of the buffer to the specified * line range. * @param start The first line * @param end The last line * @since jEdit 4.2pre1 */ public void narrow(int start, int end) { if(start > end || start < 0 || end >= buffer.getLineCount()) throw new ArrayIndexOutOfBoundsException(start + ", " + end); if(start < getFirstVisibleLine() || end > getLastVisibleLine()) expandAllFolds(); if(start != 0) hideLineRange(0,start - 1); if(end != buffer.getLineCount() - 1) hideLineRange(end + 1,buffer.getLineCount() - 1); // if we narrowed to a single collapsed fold if(start != buffer.getLineCount() - 1 && !isLineVisible(start + 1)) expandFold(start,false); // Hack... need a more direct way of obtaining a view? // JEditTextArea.getView() method? GUIUtilities.getView(textArea).getStatus().setMessageAndClear( jEdit.getProperty("view.status.narrow")); _notifyScreenLineChanges(); textArea.foldStructureChanged(); } //}}} //{{{ Package-private members boolean softWrap; int wrapMargin; FirstLine firstLine; ScrollLineCount scrollLineCount; //{{{ init() method void init() { if(!initialized) { initialized = true; fvm = new int[2]; if(buffer.isLoaded()) bufferChangeHandler.foldHandlerChanged(buffer); else fvmreset(); _notifyScreenLineChanges(); } else { updateWrapSettings(); _notifyScreenLineChanges(); textArea.updateScrollBars(); textArea.recalculateLastPhysicalLine(); } } //}}} //{{{ setScreenLineCount() method /** * Sets the number of screen lines that the specified physical line * is split into. * @since jEdit 4.2pre1 */ void setScreenLineCount(int line, int count) { int oldCount = lineMgr.getScreenLineCount(line); // still have to call this even if it equals the // old one so that the offset manager sets the // validity flag! lineMgr.setScreenLineCount(line,count); // this notifies each display manager editing this // buffer of the screen line count change if(count != oldCount) { Iterator iter = ((List)bufferMap.get(buffer)) .iterator(); while(iter.hasNext()) { ((DisplayManager)iter.next())._setScreenLineCount( line,oldCount,count); } } } //}}} //{{{ updateWrapSettings() method void updateWrapSettings() { String wrap = buffer.getStringProperty("wrap"); softWrap = wrap.equals("soft"); if(textArea.maxLineLen <= 0) { softWrap = false; wrapMargin = 0; } else { // stupidity char[] foo = new char[textArea.maxLineLen]; for(int i = 0; i < foo.length; i++) { foo[i] = ' '; } TextAreaPainter painter = textArea.getPainter(); wrapMargin = (int)painter.getFont().getStringBounds( foo,0,foo.length, painter.getFontRenderContext()) .getWidth(); } } //}}} //{{{ _notifyScreenLineChanges() method void _notifyScreenLineChanges() { if(Debug.SCROLL_DEBUG) Log.log(Log.DEBUG,this,"_notifyScreenLineChanges()"); // when the text area switches to us, it will do // a reset anyway
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -