View Javadoc

1   /***
2    * Redistribution  and use  in source  and binary  forms, with  or without
3    * modification, are permitted provided  that the following conditions are
4    * met :
5    *
6    * . Redistributions  of  source  code  must  retain  the  above copyright
7    *   notice, this list of conditions and the following disclaimer.
8    *
9    * . Redistributions in  binary form  must reproduce  the above  copyright
10   *   notice, this list of conditions  and the following disclaimer in  the
11   *   documentation and/or other materials provided with the distribution.
12   *
13   * . The name of the author may not be used to endorse or promote products
14   *   derived from this software without specific prior written permission.
15   *
16   * THIS SOFTWARE IS  PROVIDED BY THE  AUTHOR ``AS IS''  AND ANY EXPRESS  OR
17   * IMPLIED  WARRANTIES,  INCLUDING,  BUT   NOT  LIMITED  TO,  THE   IMPLIED
18   * WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE ARE
19   * DISCLAIMED.  IN NO  EVENT SHALL  THE AUTHOR  BE LIABLE  FOR ANY  DIRECT,
20   * INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR  CONSEQUENTIAL  DAMAGES
21   * (INCLUDING,  BUT  NOT LIMITED  TO,  PROCUREMENT OF  SUBSTITUTE  GOODS OR
22   * SERVICES;  LOSS  OF USE,  DATA,  OR PROFITS;  OR  BUSINESS INTERRUPTION)
23   * HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN  CONTRACT,
24   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25   * ANY  WAY  OUT OF  THE  USE OF  THIS  SOFTWARE, EVEN  IF  ADVISED OF  THE
26   * POSSIBILITY OF SUCH DAMAGE.
27   *
28   * $Id$
29   */
30  
31  package palmed.edit.text;
32  
33  import java.io.IOException;
34  import java.io.InputStream;
35  import java.io.OutputStream;
36  import palmed.edit.util.Coordinate;
37  
38  /***
39   * This class implements a text chunk.
40   *
41   * @author Mathieu Champlon
42   * @version $Revision$ $Date$
43   */
44  final class Chunk implements ITextView, ICachable, IChunk
45  {
46      /***
47       * The underlying text.
48       */
49      private IText text_;
50      /***
51       * The current number of columns and lines of the text.
52       */
53      private int columns_, lines_;
54      /***
55       * First and last line length for caching purpose.
56       */
57      private int firstLineLength_, lastLineLength_;
58      /***
59       * The modification flag.
60       */
61      private boolean hasBeenModified_;
62      /***
63       * The cache.
64       */
65      private final ICache cache_;
66  
67      /***
68       * Create a text chunk.
69       *
70       * @param cache the cache
71       */
72      public Chunk( final ICache cache )
73      {
74          if( cache == null )
75              throw new IllegalArgumentException( "parameter 'cache' is null" );
76          cache_ = cache;
77          text_ = new Text();
78          text_.register( this );
79      }
80  
81      private IText getText()
82      {
83          if( text_ == null )
84          {
85              text_ = new Text();
86              cache_.wake( this );
87              text_.register( this );
88          }
89          return text_;
90      }
91  
92      /***
93       * {@inheritDoc}
94       */
95      public void sleep()
96      {
97          text_ = null;
98      }
99  
100     /***
101      * {@inheritDoc}
102      */
103     public int getHeight()
104     {
105         return lines_;
106     }
107 
108     /***
109      * {@inheritDoc}
110      */
111     public void update( final int columns, final int lines )
112     {
113         columns_ = columns;
114         lines_ = lines - 1;
115         firstLineLength_ = getText().getLine( 0 ).length();
116         lastLineLength_ = getText().getLine( lines_ ).length();
117     }
118 
119     /***
120      * {@inheritDoc}
121      */
122     public void modified( final boolean status )
123     {
124         hasBeenModified_ = status;
125     }
126 
127     /***
128      * {@inheritDoc}
129      */
130     public boolean hasBeenModified()
131     {
132         return hasBeenModified_;
133     }
134 
135     /***
136      * {@inheritDoc}
137      */
138     public int handle( final ILineExtractor functor, final int line )
139     {
140         final int lines = lines_; // lines_ can be changed by the functor
141         if( line <= lines )
142             functor.select( getText(), line );
143         return lines;
144     }
145 
146     /***
147      * {@inheritDoc}
148      */
149     public Coordinate handle( final ITextExtractor functor, final Coordinate start, final Coordinate from,
150             final Coordinate to ) // FIXME might not be very efficient : modify start in place ?
151     {
152         final int lines = lines_; // can be changed by the functor
153         if( from.y_ - start.y_ <= lines )
154         {
155             final int length = lastLineLength_; // can be changed by the functor
156             final Coordinate translatedFrom = translate( from, start );
157             final Coordinate translatedTo = translate( to, start );
158             if( !translatedTo.equals( translatedFrom ) )
159                 functor.select( getText(), translatedFrom, translatedTo );
160             if( from.y_ - start.y_ == 0 )
161                 return new Coordinate( start.x_ + length, start.y_ + lines );
162             return new Coordinate( length, start.y_ + lines );
163         }
164         return new Coordinate( start.x_, start.y_ + lines );
165     }
166 
167     private Coordinate translate( final Coordinate coordinate, final Coordinate start )
168     {
169         if( coordinate.y_ < start.y_ )
170             return new Coordinate( 0, 0 );
171         if( coordinate.y_ > start.y_ + lines_ )
172             return new Coordinate( lastLineLength_, lines_ );
173         final int y = coordinate.y_ - start.y_;
174         if( coordinate.x_ <= start.x_ )
175             return new Coordinate( 0, y );
176         final int x = getText().getLine( y ).length();
177         if( coordinate.x_ >= start.x_ + x )
178             return new Coordinate( x, y );
179         return new Coordinate( coordinate.x_ - start.x_, y );
180     }
181 
182     /***
183      * {@inheritDoc}
184      */
185     public int count( final Coordinate size, final int previous )
186     {
187         final int length = previous + firstLineLength_;
188         size.x_ = Math.max( size.x_, Math.max( length, columns_ ) );
189         size.y_ += lines_;
190         if( lines_ > 0 )
191             return lastLineLength_;
192         return length;
193     }
194 
195     /***
196      * {@inheritDoc}
197      */
198     public void marshall( final OutputStream stream ) throws IOException
199     {
200         getText().marshall( stream );
201     }
202 
203     /***
204      * {@inheritDoc}
205      */
206     public void unmarshall( final InputStream stream ) throws IOException
207     {
208         getText().unmarshall( stream );
209     }
210 
211     /***
212      * {@inheritDoc}
213      */
214     public void read( final InputStream stream ) throws IOException
215     {
216         getText().read( stream );
217     }
218 
219     /***
220      * {@inheritDoc}
221      */
222     public void write( final OutputStream stream ) throws IOException
223     {
224         getText().write( stream );
225     }
226 }