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.selection;
32  
33  import java.io.DataInputStream;
34  import java.io.DataOutputStream;
35  import java.io.IOException;
36  import java.io.InputStream;
37  import java.io.OutputStream;
38  import java.util.Enumeration;
39  import java.util.Vector;
40  import palmed.edit.text.IText;
41  import palmed.edit.util.Coordinate;
42  
43  /***
44   * This class manages the text selection.
45   *
46   * @author Mathieu Champlon
47   * @version $Revision$ $Date$
48   */
49  public final class Selection implements ISelection
50  {
51      /***
52       * The text.
53       */
54      private final IText text_;
55      /***
56       * The current selection start.
57       */
58      private final Coordinate from_;
59      /***
60       * The current selection end.
61       */
62      private final Coordinate to_;
63      /***
64       * The current ordered selection start.
65       */
66      private Coordinate start_;
67      /***
68       * The current ordered selection end.
69       */
70      private Coordinate end_;
71      /***
72       * The views.
73       */
74      private final Vector views_;
75  
76      /***
77       * Create a selection.
78       *
79       * @param text the text
80       */
81      public Selection( final IText text )
82      {
83          if( text == null )
84              throw new IllegalArgumentException( "parameter 'text' is null" );
85          text_ = text;
86          from_ = new Coordinate();
87          to_ = new Coordinate();
88          start_ = from_;
89          end_ = to_;
90          views_ = new Vector();
91      }
92  
93      /***
94       * {@inheritDoc}
95       */
96      public boolean isEmpty()
97      {
98          return from_.equals( to_ );
99      }
100 
101     /***
102      * {@inheritDoc}
103      */
104     public void forward()
105     {
106         final String line = text_.getLine( to_.y_ );
107         if( line != null && to_.x_ < line.length() )
108         {
109             to_.x_++;
110             reorder();
111         }
112         else if( to_.y_ < text_.getHeight() - 1 )
113         {
114             to_.x_ = 0;
115             to_.y_++;
116             reorder();
117         }
118     }
119 
120     /***
121      * {@inheritDoc}
122      */
123     public void backward()
124     {
125         if( to_.x_ > 0 )
126         {
127             to_.x_--;
128             reorder();
129         }
130         else if( to_.y_ > 0 )
131         {
132             to_.y_--;
133             to_.x_ = text_.getLine( to_.y_ ).length();
134             reorder();
135         }
136     }
137 
138     private void reorder()
139     {
140         if( from_.lessThan( to_ ) )
141         {
142             start_ = from_;
143             end_ = to_;
144         }
145         else
146         {
147             start_ = to_;
148             end_ = from_;
149         }
150         notify( to_ );
151     }
152 
153     /***
154      * {@inheritDoc}
155      */
156     public void extend( final int x, final int y )
157     {
158         to_.y_ = Math.max( 0, Math.min( text_.getHeight() - 1, y ) );
159         to_.x_ = Math.max( 0, Math.min( text_.getLine( to_.y_ ).length(), x ) );
160         reorder();
161     }
162 
163     /***
164      * {@inheritDoc}
165      */
166     public void clear()
167     {
168         from_.x_ = to_.x_;
169         from_.y_ = to_.y_;
170         notify( to_ );
171     }
172 
173     /***
174      * {@inheritDoc}
175      */
176     public void delete()
177     {
178         if( !start_.equals( end_ ) )
179         {
180             text_.remove( start_, end_ );
181             end_.x_ = start_.x_;
182             end_.y_ = start_.y_;
183             clear();
184         }
185     }
186 
187     /***
188      * {@inheritDoc}
189      */
190     public void accept( final ILineVisitor visitor, final int y )
191     {
192         final String line = text_.getLine( y );
193         if( line != null )
194             visitor.visit( line, getStart( y ), getEnd( y ), y >= start_.y_ && y < end_.y_ );
195     }
196 
197     private int getStart( final int y )
198     {
199         if( start_.y_ == y )
200             return start_.x_;
201         return 0;
202     }
203 
204     private int getEnd( final int y )
205     {
206         if( y >= start_.y_ && y < end_.y_ )
207             return text_.getLine( y ).length();
208         if( end_.y_ == y )
209             return end_.x_;
210         return 0;
211     }
212 
213     /***
214      * {@inheritDoc}
215      */
216     public void unmarshall( final InputStream stream ) throws IOException
217     {
218         from_.unmarshall( stream );
219         to_.unmarshall( stream );
220         reorder();
221     }
222 
223     /***
224      * {@inheritDoc}
225      */
226     public void marshall( final OutputStream stream ) throws IOException
227     {
228         from_.marshall( stream );
229         to_.marshall( stream );
230     }
231 
232     /***
233      * {@inheritDoc}
234      */
235     public void reset()
236     {
237         from_.x_ = 0;
238         from_.y_ = 0;
239         to_.x_ = 0;
240         to_.y_ = 0;
241         notify( to_ );
242     }
243 
244     /***
245      * {@inheritDoc}
246      */
247     public void register( final ISelectionView view )
248     {
249         view.update( to_ );
250         views_.addElement( view );
251     }
252 
253     private void notify( final Coordinate position )
254     {
255         final Enumeration e = views_.elements();
256         while( e.hasMoreElements() )
257             ((ISelectionView)e.nextElement()).update( position );
258     }
259 
260     /***
261      * {@inheritDoc}
262      */
263     public void copy( final OutputStream stream ) throws IOException
264     {
265         final DataOutputStream output = new DataOutputStream( stream );
266         output.writeInt( start_.x_ );
267         output.writeInt( start_.y_ );
268         output.writeInt( end_.x_ );
269         output.writeInt( end_.y_ );
270         text_.write( stream, start_, end_ );
271     }
272 
273     /***
274      * {@inheritDoc}
275      */
276     public void cut( final OutputStream stream ) throws IOException
277     {
278         copy( stream );
279         delete();
280     }
281 
282     /***
283      * {@inheritDoc}
284      */
285     public void paste( final InputStream stream ) throws IOException
286     {
287         final DataInputStream input = new DataInputStream( stream );
288         final int startX = input.readInt();
289         final int startY = input.readInt();
290         final int endX = input.readInt();
291         final int endY = input.readInt();
292         delete();
293         text_.read( stream, from_ );
294         if( startY == endY )
295             to_.x_ += endX - startX;
296         else
297         {
298             to_.x_ = endX;
299             to_.y_ += endY - startY;
300         }
301         reorder();
302     }
303 
304     /***
305      * {@inheritDoc}
306      */
307     public void read( final InputStream stream ) throws IOException
308     {
309         delete();
310         text_.read( stream, from_ );
311     }
312 
313     /***
314      * {@inheritDoc}
315      */
316     public void write( final OutputStream stream ) throws IOException
317     {
318         text_.write( stream, start_, end_ );
319     }
320 }