001: /*
002: * FirstLine.java
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 2005 Slava Pestov
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License
010: * as published by the Free Software Foundation; either version 2
011: * of the License, or any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
021: */
022:
023: package org.gjt.sp.jedit.textarea;
024:
025: import org.gjt.sp.jedit.Debug;
026: import org.gjt.sp.util.Log;
027:
028: /**
029: * This Anchor is the first visible line of the textarea.
030: *
031: * @author Slava Pestov
032: * @version $Id: FirstLine.java 10451 2007-09-02 14:42:52Z kpouer $
033: */
034: class FirstLine extends Anchor {
035: /** The skew is the scroll count from the beginning of the line. Used with soft wrap. */
036: int skew;
037:
038: //{{{ FirstLine constructor
039: FirstLine(DisplayManager displayManager, TextArea textArea) {
040: super (displayManager, textArea);
041: } //}}}
042:
043: //{{{ changed() method
044: public void changed() {
045: //{{{ Debug code
046: if (Debug.SCROLL_DEBUG) {
047: Log.log(Log.DEBUG, this , "changed() before: "
048: + physicalLine + ':' + scrollLine + ':' + skew);
049: } //}}}
050:
051: ensurePhysicalLineIsVisible();
052:
053: int screenLines = displayManager
054: .getScreenLineCount(physicalLine);
055: if (skew >= screenLines)
056: skew = screenLines - 1;
057:
058: //{{{ Debug code
059: if (Debug.SCROLL_VERIFY) {
060: System.err.println("SCROLL_VERIFY");
061: int verifyScrollLine = 0;
062:
063: for (int i = 0; i < displayManager.getBuffer()
064: .getLineCount(); i++) {
065: if (!displayManager.isLineVisible(i))
066: continue;
067:
068: if (i >= physicalLine)
069: break;
070:
071: verifyScrollLine += displayManager
072: .getScreenLineCount(i);
073: }
074:
075: if (verifyScrollLine != scrollLine) {
076: Exception ex = new Exception(scrollLine + ":"
077: + verifyScrollLine);
078: Log.log(Log.ERROR, this , ex);
079: }
080: }
081:
082: if (Debug.SCROLL_DEBUG) {
083: Log.log(Log.DEBUG, this , "changed() after: " + physicalLine
084: + ':' + scrollLine + ':' + skew);
085: } //}}}
086: } //}}}
087:
088: //{{{ reset() method
089: public void reset() {
090: if (Debug.SCROLL_DEBUG)
091: Log.log(Log.DEBUG, this , "reset()");
092:
093: int oldPhysicalLine = physicalLine;
094: physicalLine = 0;
095: scrollLine = 0;
096:
097: int i = displayManager.getFirstVisibleLine();
098:
099: for (;;) {
100: if (i >= oldPhysicalLine)
101: break;
102:
103: int before = scrollLine;
104: displayManager.updateScreenLineCount(i);
105: if (before != scrollLine)
106: throw new RuntimeException(this + " nudged");
107: scrollLine += displayManager.getScreenLineCount(i);
108:
109: int nextLine = displayManager.getNextVisibleLine(i);
110: if (nextLine == -1)
111: break;
112: else
113: i = nextLine;
114: }
115:
116: physicalLine = i;
117:
118: displayManager.updateScreenLineCount(i);
119: int screenLines = displayManager
120: .getScreenLineCount(physicalLine);
121: if (skew >= screenLines)
122: skew = screenLines - 1;
123:
124: textArea.updateScrollBar();
125: } //}}}
126:
127: //{{{ physDown() method
128: // scroll down by physical line amount
129: void physDown(int amount, int screenAmount) {
130: if (Debug.SCROLL_DEBUG) {
131: Log.log(Log.DEBUG, this , "physDown() start: "
132: + physicalLine + ':' + scrollLine);
133: }
134:
135: skew = 0;
136:
137: if (!displayManager.isLineVisible(physicalLine)) {
138: int lastVisibleLine = displayManager.getLastVisibleLine();
139: if (physicalLine > lastVisibleLine)
140: physicalLine = lastVisibleLine;
141: else {
142: int nextPhysicalLine = displayManager
143: .getNextVisibleLine(physicalLine);
144: amount -= nextPhysicalLine - physicalLine;
145: scrollLine += displayManager
146: .getScreenLineCount(physicalLine);
147: physicalLine = nextPhysicalLine;
148: }
149: }
150:
151: for (;;) {
152: int nextPhysicalLine = displayManager
153: .getNextVisibleLine(physicalLine);
154: if (nextPhysicalLine == -1)
155: break;
156: else if (nextPhysicalLine > physicalLine + amount)
157: break;
158: else {
159: scrollLine += displayManager
160: .getScreenLineCount(physicalLine);
161: amount -= nextPhysicalLine - physicalLine;
162: physicalLine = nextPhysicalLine;
163: }
164: }
165:
166: if (Debug.SCROLL_DEBUG) {
167: Log.log(Log.DEBUG, this , "physDown() end: " + physicalLine
168: + ':' + scrollLine);
169: }
170:
171: callChanged = true;
172:
173: // JEditTextArea.scrollTo() needs this to simplify
174: // its code
175: if (screenAmount < 0)
176: scrollUp(-screenAmount);
177: else if (screenAmount > 0)
178: scrollDown(screenAmount);
179: } //}}}
180:
181: //{{{ physUp() method
182: // scroll up by physical line amount
183: void physUp(int amount, int screenAmount) {
184: if (Debug.SCROLL_DEBUG) {
185: Log.log(Log.DEBUG, this , "physUp() start: " + physicalLine
186: + ':' + scrollLine);
187: }
188:
189: skew = 0;
190:
191: if (!displayManager.isLineVisible(physicalLine)) {
192: int firstVisibleLine = displayManager.getFirstVisibleLine();
193: if (physicalLine < firstVisibleLine)
194: physicalLine = firstVisibleLine;
195: else {
196: int prevPhysicalLine = displayManager
197: .getPrevVisibleLine(physicalLine);
198: amount -= physicalLine - prevPhysicalLine;
199: }
200: }
201:
202: for (;;) {
203: int prevPhysicalLine = displayManager
204: .getPrevVisibleLine(physicalLine);
205: if (prevPhysicalLine == -1)
206: break;
207: else if (prevPhysicalLine < physicalLine - amount)
208: break;
209: else {
210: amount -= physicalLine - prevPhysicalLine;
211: physicalLine = prevPhysicalLine;
212: scrollLine -= displayManager
213: .getScreenLineCount(prevPhysicalLine);
214: }
215: }
216:
217: if (Debug.SCROLL_DEBUG) {
218: Log.log(Log.DEBUG, this , "physUp() end: " + physicalLine
219: + ':' + scrollLine);
220: }
221:
222: callChanged = true;
223:
224: // JEditTextArea.scrollTo() needs this to simplify
225: // its code
226: if (screenAmount < 0)
227: scrollUp(-screenAmount);
228: else if (screenAmount > 0)
229: scrollDown(screenAmount);
230: } //}}}
231:
232: //{{{ scrollDown() method
233: // scroll down by screen line amount
234: void scrollDown(int amount) {
235: if (Debug.SCROLL_DEBUG)
236: Log.log(Log.DEBUG, this , "scrollDown()");
237:
238: ensurePhysicalLineIsVisible();
239:
240: amount += skew;
241:
242: skew = 0;
243:
244: while (amount > 0) {
245: int screenLines = displayManager
246: .getScreenLineCount(physicalLine);
247: if (amount < screenLines) {
248: skew = amount;
249: break;
250: } else {
251: int nextLine = displayManager
252: .getNextVisibleLine(physicalLine);
253: if (nextLine == -1)
254: break;
255: boolean visible = displayManager
256: .isLineVisible(physicalLine);
257: physicalLine = nextLine;
258: if (visible) {
259: amount -= screenLines;
260: scrollLine += screenLines;
261: }
262: }
263: }
264:
265: callChanged = true;
266: } //}}}
267:
268: //{{{ scrollUp() method
269: // scroll up by screen line amount
270: void scrollUp(int amount) {
271: if (Debug.SCROLL_DEBUG)
272: Log.log(Log.DEBUG, this , "scrollUp() before:" + this );
273:
274: ensurePhysicalLineIsVisible();
275:
276: if (amount <= skew) {
277: // the amount is less than the skew, so we stay in the same like, just going
278: // upper
279: skew -= amount;
280: } else {
281: // moving to the first screen line of the current physical line
282: amount -= skew;
283: skew = 0;
284:
285: while (amount > 0) {
286: int prevLine = displayManager
287: .getPrevVisibleLine(physicalLine);
288: if (prevLine == -1)
289: break;
290: // moving to the previous visible physical line
291: physicalLine = prevLine;
292:
293: int screenLines = displayManager
294: .getScreenLineCount(physicalLine);
295: scrollLine -= screenLines;
296: if (amount < screenLines) {
297: skew = screenLines - amount;
298: break;
299: } else
300: amount -= screenLines;
301: }
302: }
303:
304: if (Debug.SCROLL_DEBUG)
305: Log.log(Log.DEBUG, this , "scrollUp() after:" + this );
306: callChanged = true;
307: } //}}}
308:
309: //{{{ ensurePhysicalLineIsVisible() method
310: void ensurePhysicalLineIsVisible() {
311: if (!displayManager.isLineVisible(physicalLine)) {
312: if (physicalLine > displayManager.getLastVisibleLine()) {
313: physicalLine = displayManager.getLastVisibleLine();
314: scrollLine = displayManager.getScrollLineCount() - 1;
315: } else if (physicalLine < displayManager
316: .getFirstVisibleLine()) {
317: physicalLine = displayManager.getFirstVisibleLine();
318: scrollLine = 0;
319: } else {
320: physicalLine = displayManager
321: .getNextVisibleLine(physicalLine);
322: scrollLine += displayManager
323: .getScreenLineCount(physicalLine);
324: }
325: }
326: } //}}}
327:
328: //{{{ toString() method
329: public String toString() {
330: return "FirstLine[" + physicalLine + ',' + scrollLine + ','
331: + skew + ']';
332: } //}}}
333: }
|