KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > gjt > sp > jedit > textarea > Selection


1 /*
2  * Selection.java - Selected text
3  * :tabSize=8:indentSize=8:noTabs=false:
4  * :folding=explicit:collapseFolds=1:
5  *
6  * Copyright (C) 2001, 2005 Slava Pestov
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */

22
23 package org.gjt.sp.jedit.textarea;
24
25 //{{{ Imports
26
import java.util.ArrayList JavaDoc;
27 import java.util.List JavaDoc;
28
29 import org.gjt.sp.jedit.buffer.JEditBuffer;
30 import org.gjt.sp.util.StandardUtilities;
31 //}}}
32

33 /**
34  * An abstract class that holds data on a region of selected text.
35  * As an abstract class, it cannot be used
36  * directly, but instead serves as a parent class for two specific types
37  * of selection structures:
38  * <ul>
39  * <li>{@link Selection.Range} - represents an ordinary range of selected text.</li>
40  * <li>{@link Selection.Rect} - represents a rectangular selection.</li>
41  * </ul>
42  *
43  * @author Slava Pestov
44  * @author John Gellene (API documentation)
45  * @version $Id: Selection.java 5578 2006-07-13 10:11:37Z kpouer $
46  * @since jEdit 3.2pre1
47  */

48 public abstract class Selection implements Cloneable JavaDoc
49 {
50     //{{{ getStart() method
51
/**
52      * Returns the start offset of this selection.
53      */

54     public int getStart()
55     {
56         return start;
57     } //}}}
58

59     //{{{ getEnd() method
60
/**
61      * Returns the end offset of this selection.
62      */

63     public int getEnd()
64     {
65         return end;
66     } //}}}
67

68     //{{{ getStart() method
69
/**
70      * Returns the beginning of the portion of the selection
71      * falling on the specified line. Used to manipulate
72          * selection text on a line-by-line basis.
73      * @param buffer The buffer
74      * @param line The line number
75      * @since jEdit 4.1pre1
76      */

77     public abstract int getStart(JEditBuffer buffer, int line);
78     //}}}
79

80     //{{{ getEnd() method
81
/**
82      * Returns the end of the portion of the selection
83      * falling on the specified line. Used to manipulate
84          * selection text on a line-by-line basis.
85      * @param buffer The buffer
86      * @param line The line number
87      * @since jEdit 4.1pre1
88      */

89     public abstract int getEnd(JEditBuffer buffer, int line);
90     //}}}
91

92     //{{{ getStartLine() method
93
/**
94      * Returns the starting line number of this selection.
95      */

96     public int getStartLine()
97     {
98         return startLine;
99     } //}}}
100

101     //{{{ getEndLine() method
102
/**
103      * Returns the ending line number of this selection.
104      */

105     public int getEndLine()
106     {
107         return endLine;
108     } //}}}
109

110     //{{{ overlaps() method
111
/**
112      * Returns if this selection and the specified selection overlap.
113      * @param s The other selection
114      * @since jEdit 4.1pre1
115      */

116     public boolean overlaps(Selection s)
117     {
118         if((start >= s.start && start <= s.end)
119             || (end >= s.start && end <= s.end))
120             return true;
121         else
122             return false;
123     } //}}}
124

125     //{{{ toString() method
126
public String JavaDoc toString()
127     {
128         return getClass().getName() + "[start=" + start
129             + ",end=" + end + ",startLine=" + startLine
130             + ",endLine=" + endLine + ']';
131     } //}}}
132

133     //{{{ clone() method
134
public Object JavaDoc clone()
135     {
136         try
137         {
138             return super.clone();
139         }
140         catch(CloneNotSupportedException JavaDoc e)
141         {
142             throw new InternalError JavaDoc("I just drank a whole "
143                 + "bottle of cough syrup and I feel "
144                 + "funny!");
145         }
146     } //}}}
147

148     //{{{ Package-private members
149
int start, end;
150     int startLine, endLine;
151
152     //{{{ Selection constructor
153
Selection()
154     {
155     } //}}}
156

157     //{{{ Selection constructor
158
Selection(Selection sel)
159     {
160         this.start = sel.start;
161         this.end = sel.end;
162     } //}}}
163

164     //{{{ Selection constructor
165
Selection(int start, int end)
166     {
167         this.start = start;
168         this.end = end;
169     } //}}}
170

171     // should the next two be public, maybe?
172
abstract void getText(JEditBuffer buffer, StringBuffer JavaDoc buf);
173     abstract int setText(JEditBuffer buffer, String JavaDoc text);
174
175     abstract boolean contentInserted(JEditBuffer buffer, int startLine, int start,
176         int numLines, int length);
177     abstract boolean contentRemoved(JEditBuffer buffer, int startLine, int start,
178         int numLines, int length);
179     //}}}
180

181     //{{{ Range class
182
/**
183      * An ordinary range selection.
184      * @since jEdit 3.2pre1
185      */

186     public static class Range extends Selection
187     {
188         //{{{ Range constructor
189
public Range()
190         {
191         } //}}}
192

193         //{{{ Range constructor
194
public Range(Selection sel)
195         {
196             super(sel);
197         } //}}}
198

199         //{{{ Range constructor
200
public Range(int start, int end)
201         {
202             super(start,end);
203         } //}}}
204

205         //{{{ getStart() method
206
public int getStart(JEditBuffer buffer, int line)
207         {
208             if(line == startLine)
209                 return start;
210             else
211                 return buffer.getLineStartOffset(line);
212         } //}}}
213

214         //{{{ getEnd() method
215
public int getEnd(JEditBuffer buffer, int line)
216         {
217             if(line == endLine)
218                 return end;
219             else
220                 return buffer.getLineEndOffset(line) - 1;
221         } //}}}
222

223         //{{{ Package-private members
224

225         //{{{ getText() method
226
void getText(JEditBuffer buffer, StringBuffer JavaDoc buf)
227         {
228             buf.append(buffer.getText(start,end - start));
229         } //}}}
230

231         //{{{ setText() method
232
int setText(JEditBuffer buffer, String JavaDoc text)
233         {
234             buffer.remove(start,end - start);
235             if(text != null && text.length() != 0)
236             {
237                 buffer.insert(start,text);
238                 return start + text.length();
239             }
240             else
241                 return start;
242         } //}}}
243

244         //{{{ contentInserted() method
245
boolean contentInserted(JEditBuffer buffer, int startLine, int start,
246             int numLines, int length)
247         {
248             boolean changed = false;
249
250             if(this.start >= start)
251             {
252                 this.start += length;
253                 if(numLines != 0)
254                     this.startLine = buffer.getLineOfOffset(this.start);
255                 changed = true;
256             }
257
258             if(this.end >= start)
259             {
260                 this.end += length;
261                 if(numLines != 0)
262                     this.endLine = buffer.getLineOfOffset(this.end);
263                 changed = true;
264             }
265
266             return changed;
267         } //}}}
268

269         //{{{ contentRemoved() method
270
boolean contentRemoved(JEditBuffer buffer, int startLine, int start,
271             int numLines, int length)
272         {
273             int end = start + length;
274             boolean changed = false;
275
276             if(this.start > start && this.start <= end)
277             {
278                 this.start = start;
279                 changed = true;
280             }
281             else if(this.start > end)
282             {
283                 this.start -= length;
284                 changed = true;
285             }
286
287             if(this.end > start && this.end <= end)
288             {
289                 this.end = start;
290                 changed = true;
291             }
292             else if(this.end > end)
293             {
294                 this.end -= length;
295                 changed = true;
296             }
297
298             if(changed && numLines != 0)
299             {
300                 this.startLine = buffer.getLineOfOffset(this.start);
301                 this.endLine = buffer.getLineOfOffset(this.end);
302             }
303
304             return changed;
305         } //}}}
306

307         //}}}
308
} //}}}
309

310     //{{{ Rect class
311
/**
312      * A rectangular selection.
313      * @since jEdit 3.2pre1
314      */

315     // this class is not very fast...
316
public static class Rect extends Selection
317     {
318         //{{{ Rect constructor
319
public Rect()
320         {
321             super();
322         } //}}}
323

324         //{{{ Rect constructor
325
public Rect(Selection sel)
326         {
327             super(sel);
328         } //}}}
329

330         //{{{ Rect constructor
331
public Rect(int start, int end)
332         {
333             super(start,end);
334         } //}}}
335

336         //{{{ Rect constructor
337
public Rect(int startLine, int start, int endLine, int end)
338         {
339             this.startLine = startLine;
340             this.start = start;
341             this.endLine = endLine;
342             this.end = end;
343         } //}}}
344

345         //{{{ Rect constructor
346
public Rect(JEditBuffer buffer, int startLine, int startColumn,
347             int endLine, int endColumn)
348         {
349             this.startLine = startLine;
350             this.endLine = endLine;
351
352             int[] width = new int[1];
353             int startOffset = buffer.getOffsetOfVirtualColumn(startLine,
354                 startColumn,width);
355             if(startOffset == -1)
356             {
357                 extraStartVirt = startColumn - width[0];
358                 startOffset = buffer.getLineEndOffset(startLine) - 1;
359             }
360             else
361                 startOffset += buffer.getLineStartOffset(startLine);
362
363             int endOffset = buffer.getOffsetOfVirtualColumn(endLine,
364                 endColumn,width);
365             if(endOffset == -1)
366             {
367                 extraEndVirt = endColumn - width[0];
368                 endOffset = buffer.getLineEndOffset(endLine) - 1;
369             }
370             else
371                 endOffset += buffer.getLineStartOffset(endLine);
372         } //}}}
373

374         //{{{ getStartColumn() method
375
public int getStartColumn(JEditBuffer buffer)
376         {
377             int virtColStart = buffer.getVirtualWidth(startLine,
378                 start - buffer.getLineStartOffset(startLine)) + extraStartVirt;
379             int virtColEnd = buffer.getVirtualWidth(endLine,
380                 end - buffer.getLineStartOffset(endLine)) + extraEndVirt;
381             return Math.min(virtColStart,virtColEnd);
382         } //}}}
383

384         //{{{ getEndColumn() method
385
public int getEndColumn(JEditBuffer buffer)
386         {
387             int virtColStart = buffer.getVirtualWidth(startLine,
388                 start - buffer.getLineStartOffset(startLine)) + extraStartVirt;
389             int virtColEnd = buffer.getVirtualWidth(endLine,
390                 end - buffer.getLineStartOffset(endLine)) + extraEndVirt;
391             return Math.max(virtColStart,virtColEnd);
392         } //}}}
393

394         //{{{ getStart() method
395
public int getStart(JEditBuffer buffer, int line)
396         {
397             return getColumnOnOtherLine(buffer,line,
398                 getStartColumn(buffer));
399         } //}}}
400

401         //{{{ getEnd() method
402
public int getEnd(JEditBuffer buffer, int line)
403         {
404             return getColumnOnOtherLine(buffer,line,
405                 getEndColumn(buffer));
406         } //}}}
407

408         //{{{ Package-private members
409
int extraStartVirt;
410         int extraEndVirt;
411
412         //{{{ getText() method
413
void getText(JEditBuffer buffer, StringBuffer JavaDoc buf)
414         {
415             int start = getStartColumn(buffer);
416             int end = getEndColumn(buffer);
417
418             for(int i = startLine; i <= endLine; i++)
419             {
420                 int lineStart = buffer.getLineStartOffset(i);
421                 int lineLen = buffer.getLineLength(i);
422
423                 int rectStart = buffer.getOffsetOfVirtualColumn(
424                     i,start,null);
425                 if(rectStart == -1)
426                     rectStart = lineLen;
427
428                 int rectEnd = buffer.getOffsetOfVirtualColumn(
429                     i,end,null);
430                 if(rectEnd == -1)
431                     rectEnd = lineLen;
432
433                 if(rectEnd < rectStart)
434                     System.err.println(i + ":::" + start + ':' + end
435                         + " ==> " + rectStart + ':' + rectEnd);
436                 buf.append(buffer.getText(lineStart + rectStart,
437                     rectEnd - rectStart));
438
439                 if(i != endLine)
440                     buf.append('\n');
441             }
442         } //}}}
443

444         //{{{ setText() method
445
int setText(JEditBuffer buffer, String JavaDoc text)
446         {
447             int startColumn = getStartColumn(buffer);
448             int endColumn = getEndColumn(buffer);
449
450             int tabSize = buffer.getTabSize();
451
452             int maxWidth = 0;
453             int totalLines = 0;
454             List JavaDoc lines = new ArrayList JavaDoc();
455
456             //{{{ Split the text into lines
457
if(text != null)
458             {
459                 int lastNewline = 0;
460                 int currentWidth = startColumn;
461                 for(int i = 0; i < text.length(); i++)
462                 {
463                     char ch = text.charAt(i);
464                     if(ch == '\n')
465                     {
466                         totalLines++;
467                         lines.add(text.substring(
468                             lastNewline,i));
469                         lastNewline = i + 1;
470                         maxWidth = Math.max(maxWidth,currentWidth);
471                         lines.add(currentWidth);
472                         currentWidth = startColumn;
473                     }
474                     else if(ch == '\t')
475                         currentWidth += tabSize - (currentWidth % tabSize);
476                     else
477                         currentWidth++;
478                 }
479
480                 if(lastNewline != text.length())
481                 {
482                     totalLines++;
483                     lines.add(text.substring(lastNewline));
484                     lines.add(currentWidth);
485                     maxWidth = Math.max(maxWidth,currentWidth);
486                 }
487             } //}}}
488

489             //{{{ Insert the lines into the buffer
490
int endOffset = 0;
491             int[] total = new int[1];
492             int lastLine = Math.max(startLine + totalLines - 1,endLine);
493             for(int i = startLine; i <= lastLine; i++)
494             {
495                 if(i == buffer.getLineCount())
496                     buffer.insert(buffer.getLength(),"\n");
497
498                 int lineStart = buffer.getLineStartOffset(i);
499                 int lineLen = buffer.getLineLength(i);
500
501                 int rectStart = buffer.getOffsetOfVirtualColumn(
502                     i,startColumn,total);
503                 int startWhitespace;
504                 if(rectStart == -1)
505                 {
506                     startWhitespace = startColumn - total[0];
507                     rectStart = lineLen;
508                 }
509                 else
510                     startWhitespace = 0;
511
512                 int rectEnd = buffer.getOffsetOfVirtualColumn(
513                     i,endColumn,null);
514                 if(rectEnd == -1)
515                     rectEnd = lineLen;
516
517                 buffer.remove(rectStart + lineStart,rectEnd - rectStart);
518
519                 if(startWhitespace != 0)
520                 {
521                     buffer.insert(rectStart + lineStart,
522                         StandardUtilities.createWhiteSpace(startWhitespace,0));
523                 }
524
525                 int endWhitespace;
526                 if(totalLines == 0)
527                 {
528                     if(rectEnd == lineLen)
529                         endWhitespace = 0;
530                     else
531                         endWhitespace = maxWidth - startColumn;
532                 }
533                 else
534                 {
535                     int index = 2 * ((i - startLine) % totalLines);
536                     String JavaDoc str = (String JavaDoc)lines.get(index);
537                     buffer.insert(rectStart + lineStart + startWhitespace,str);
538                     if(rectEnd == lineLen)
539                         endWhitespace = 0;
540                     else
541                     {
542                         endWhitespace = maxWidth
543                             - (Integer JavaDoc) lines.get(index + 1);
544                     }
545                     startWhitespace += str.length();
546                 }
547
548                 if(endWhitespace != 0)
549                 {
550                     buffer.insert(rectStart + lineStart
551                         + startWhitespace,
552                         StandardUtilities.createWhiteSpace(endWhitespace,0));
553                 }
554
555                 endOffset = rectStart + lineStart
556                     + startWhitespace
557                     + endWhitespace;
558             } //}}}
559

560             //{{{ Move the caret down a line
561
if(text == null || text.length() == 0)
562                 return end;
563             else
564                 return endOffset;
565             //}}}
566
} //}}}
567

568         //{{{ contentInserted() method
569
boolean contentInserted(JEditBuffer buffer, int startLine, int start,
570             int numLines, int length)
571         {
572             if(this.end < start)
573                 return false;
574
575             this.end += length;
576
577             if(this.startLine > startLine)
578             {
579                 this.start += length;
580                 if(numLines != 0)
581                 {
582                     this.startLine = buffer.getLineOfOffset(
583                         this.start);
584                     this.endLine = buffer.getLineOfOffset(
585                         this.end);
586                 }
587                 return true;
588             }
589
590             int endVirtualColumn = buffer.getVirtualWidth(
591                 this.endLine,end
592                 - buffer.getLineStartOffset(this.endLine));
593
594             if(this.start == start)
595             {
596                 int startVirtualColumn = buffer.getVirtualWidth(
597                     this.startLine,start
598                     - buffer.getLineStartOffset(
599                     this.startLine));
600
601                 this.start += length;
602
603                 int newStartVirtualColumn
604                     = buffer.getVirtualWidth(
605                         startLine,start -
606                         buffer.getLineStartOffset(
607                         this.startLine));
608
609                 int[] totalVirtualWidth = new int[1];
610                 int newEnd = buffer.getOffsetOfVirtualColumn(
611                     this.endLine,endVirtualColumn +
612                     newStartVirtualColumn -
613                     startVirtualColumn,
614                     totalVirtualWidth);
615
616                 if(newEnd != -1)
617                 {
618                     end = buffer.getLineStartOffset(
619                         this.endLine) + newEnd;
620                 }
621                 else
622                 {
623                     end = buffer.getLineEndOffset(
624                         this.endLine) - 1;
625                     extraEndVirt = totalVirtualWidth[0]
626                         - endVirtualColumn;
627                 }
628             }
629             else if(this.start > start)
630             {
631                 this.start += length;
632                 if(numLines != 0)
633                 {
634                     this.startLine = buffer.getLineOfOffset(
635                         this.start);
636                 }
637             }
638
639             if(numLines != 0)
640                 this.endLine = buffer.getLineOfOffset(this.end);
641             int newEndVirtualColumn = buffer.getVirtualWidth(
642                 endLine,
643                 end - buffer.getLineStartOffset(this.endLine));
644             if(startLine == this.endLine && extraEndVirt != 0)
645             {
646                 extraEndVirt += endVirtualColumn - newEndVirtualColumn;
647             }
648             else if(startLine == this.startLine
649                 && extraStartVirt != 0)
650             {
651                 extraStartVirt += endVirtualColumn - newEndVirtualColumn;
652             }
653
654             return true;
655         } //}}}
656

657         //{{{ contentRemoved() method
658
boolean contentRemoved(JEditBuffer buffer, int startLine, int start,
659             int numLines, int length)
660         {
661             int end = start + length;
662             boolean changed = false;
663
664             if(this.start > start && this.start <= end)
665             {
666                 this.start = start;
667                 changed = true;
668             }
669             else if(this.start > end)
670             {
671                 this.start -= length;
672                 changed = true;
673             }
674
675             if(this.end > start && this.end <= end)
676             {
677                 this.end = start;
678                 changed = true;
679             }
680             else if(this.end > end)
681             {
682                 this.end -= length;
683                 changed = true;
684             }
685
686             if(changed && numLines != 0)
687             {
688                 this.startLine = buffer.getLineOfOffset(this.start);
689                 this.endLine = buffer.getLineOfOffset(this.end);
690             }
691
692             return changed;
693         } //}}}
694

695         //}}}
696

697         //{{{ Private members
698

699         //{{{ getColumnOnOtherLine() method
700
private static int getColumnOnOtherLine(JEditBuffer buffer, int line,
701             int col)
702         {
703             int returnValue = buffer.getOffsetOfVirtualColumn(
704                 line,col,null);
705             if(returnValue == -1)
706                 return buffer.getLineEndOffset(line) - 1;
707             else
708                 return buffer.getLineStartOffset(line) + returnValue;
709         } //}}}
710

711         //}}}
712
} //}}}
713
}
714
Popular Tags