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.view; 32 33 import java.io.IOException; 34 import java.io.InputStream; 35 import java.io.OutputStream; 36 import java.util.Enumeration; 37 import java.util.Vector; 38 import palmed.edit.selection.ILineVisitor; 39 import palmed.edit.util.Coordinate; 40 41 /*** 42 * This class implements a viewport on a content. 43 * 44 * @author Mathieu Champlon 45 * @version $Revision$ $Date$ 46 */ 47 public final class Viewport implements IViewport, IContent, IView 48 { 49 /*** 50 * The current upper-left character coordinate. 51 */ 52 private final Coordinate scroll_; 53 /*** 54 * Visible text size in characters. 55 */ 56 private int visibleColumns_, visibleLines_; 57 /*** 58 * Current text size in characters. 59 */ 60 private int maxColumns_, maxLines_; 61 /*** 62 * The current cursor position. 63 */ 64 private final Coordinate cursorPosition_; 65 /*** 66 * The content. 67 */ 68 private final IContent content_; 69 /*** 70 * The view. 71 */ 72 private IView view_; 73 /*** 74 * The scroll views. 75 */ 76 private final Vector views_; 77 78 /*** 79 * Create a content viewport. 80 * 81 * @param content the content to manage 82 */ 83 public Viewport( final IContent content ) 84 { 85 if( content == null ) 86 throw new IllegalArgumentException( "parameter 'content' is null" ); 87 content_ = content; 88 scroll_ = new Coordinate(); 89 view_ = new NullView(); 90 cursorPosition_ = new Coordinate(); 91 views_ = new Vector(); 92 content_.register( this ); 93 } 94 95 /*** 96 * {@inheritDoc} 97 */ 98 public void type( final int keyCode ) 99 { 100 content_.type( keyCode ); 101 showCursor(); 102 } 103 104 /*** 105 * {@inheritDoc} 106 */ 107 public void drag( final int x, final int y ) 108 { 109 content_.drag( x + scroll_.x_, y + scroll_.y_ ); 110 showCursor(); 111 } 112 113 /*** 114 * {@inheritDoc} 115 */ 116 public void click( final int x, final int y ) 117 { 118 content_.click( x + scroll_.x_, y + scroll_.y_ ); 119 showCursor(); 120 } 121 122 /*** 123 * {@inheritDoc} 124 */ 125 public void enter() 126 { 127 content_.enter(); 128 showCursor(); 129 } 130 131 /*** 132 * {@inheritDoc} 133 */ 134 public void backspace() 135 { 136 content_.backspace(); 137 showCursor(); 138 } 139 140 /*** 141 * {@inheritDoc} 142 */ 143 public void accept( final ILineVisitor visitor, final int y ) 144 { 145 content_.accept( new TranslatedLineVisitor( visitor, scroll_.x_ ), y + scroll_.y_ ); 146 } 147 148 /*** 149 * {@inheritDoc} 150 */ 151 public void register( final IView view ) 152 { 153 if( view == null ) 154 throw new IllegalArgumentException( "parameter 'view' is null" ); 155 view_ = view; 156 } 157 158 /*** 159 * {@inheritDoc} 160 */ 161 public void scroll( final int columns, final int lines ) 162 { 163 scroll_.x_ += columns; 164 scroll_.y_ += lines; 165 center(); 166 } 167 168 /*** 169 * {@inheritDoc} 170 */ 171 public void update( final Coordinate position ) 172 { 173 cursorPosition_.x_ = position.x_; 174 cursorPosition_.y_ = position.y_; 175 view_.update( new Coordinate( cursorPosition_.x_ - scroll_.x_, cursorPosition_.y_ - scroll_.y_ ) ); 176 } 177 178 /*** 179 * {@inheritDoc} 180 */ 181 public void update( final int columns, final int lines ) 182 { 183 maxColumns_ = columns; 184 maxLines_ = lines; 185 center(); 186 } 187 188 /*** 189 * {@inheritDoc} 190 */ 191 public void modified( final boolean status ) 192 { 193 view_.modified( status ); 194 } 195 196 /*** 197 * {@inheritDoc} 198 */ 199 public void resize( final int columns, final int lines ) 200 { 201 visibleColumns_ = columns; 202 visibleLines_ = lines; 203 center(); 204 } 205 206 private void center() 207 { 208 scroll_.x_ = Math.max( 0, Math.min( scroll_.x_, maxColumns_ - visibleColumns_ ) ); 209 scroll_.y_ = Math.max( 0, Math.min( scroll_.y_, maxLines_ - visibleLines_ ) ); 210 view_.update( new Coordinate( cursorPosition_.x_ - scroll_.x_, cursorPosition_.y_ - scroll_.y_ ) ); 211 view_.update( maxColumns_, maxLines_ ); 212 final Enumeration e = views_.elements(); 213 while( e.hasMoreElements() ) 214 ((IScrollView)e.nextElement()).scrolled( scroll_ ); 215 } 216 217 /*** 218 * {@inheritDoc} 219 */ 220 public void register( final IScrollView view ) 221 { 222 if( view == null ) 223 throw new IllegalArgumentException( "parameter 'view' is null" ); 224 views_.addElement( view ); 225 view.scrolled( scroll_ ); 226 } 227 228 /*** 229 * {@inheritDoc} 230 */ 231 public void unmarshall( final InputStream stream ) throws IOException 232 { 233 scroll_.unmarshall( stream ); 234 content_.unmarshall( stream ); 235 } 236 237 /*** 238 * {@inheritDoc} 239 */ 240 public void marshall( final OutputStream stream ) throws IOException 241 { 242 scroll_.marshall( stream ); 243 content_.marshall( stream ); 244 } 245 246 /*** 247 * {@inheritDoc} 248 */ 249 public void clear() 250 { 251 content_.clear(); 252 } 253 254 private void showCursor() 255 { 256 scroll( nearestColumn( cursorPosition_.x_ - scroll_.x_ ), nearestLine( cursorPosition_.y_ - scroll_.y_ ) ); 257 } 258 259 private int nearestLine( final int y ) 260 { 261 if( visibleLines_ > 0 ) 262 { 263 if( y >= visibleLines_ ) 264 return y - visibleLines_ + 1; 265 else if( y < 0 ) 266 return y; 267 } 268 return 0; 269 } 270 271 private int nearestColumn( final int x ) 272 { 273 if( visibleColumns_ > 0 ) 274 { 275 if( x > visibleColumns_ ) 276 return x - visibleColumns_; 277 else if( x <= 0 ) 278 return x - 1; 279 } 280 return 0; 281 } 282 283 /*** 284 * {@inheritDoc} 285 */ 286 public void copy( final OutputStream stream ) throws IOException 287 { 288 content_.copy( stream ); 289 } 290 291 /*** 292 * {@inheritDoc} 293 */ 294 public void cut( final OutputStream stream ) throws IOException 295 { 296 content_.cut( stream ); 297 showCursor(); 298 } 299 300 /*** 301 * {@inheritDoc} 302 */ 303 public void paste( final InputStream stream ) throws IOException 304 { 305 content_.paste( stream ); 306 showCursor(); 307 } 308 309 /*** 310 * {@inheritDoc} 311 */ 312 public void undo() 313 { 314 content_.undo(); 315 showCursor(); 316 } 317 318 /*** 319 * {@inheritDoc} 320 */ 321 public void redo() 322 { 323 content_.redo(); 324 showCursor(); 325 } 326 }