View Javadoc

    1   /*
    2    * All Rights Reserved.
    3    * Copyright (C) 1999-2005 Tsukuba Bunko.
    4    *
    5    * Licensed under the BSD License ("the License"); you may not use
    6    * this file except in compliance with the License.
    7    * You may obtain a copy of the License at
    8    *
    9    *       http://www.tsukuba-bunko.org/licenses/LICENSE.txt
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   * $Id: Page.java,v 1.5 2005/08/06 18:58:03 ppoi Exp $
    18   */
    19  package tsukuba_bunko.peko.canvas.text;
    20
    21  import	java.awt.Color;
    22  import	java.awt.Dimension;
    23  import	java.awt.Font;
    24  import	java.awt.Insets;
    25  import	java.awt.Point;
    26
    27  import	java.awt.font.FontRenderContext;
    28
    29  import	java.io.Serializable;
    30
    31  import	java.util.List;
    32
    33  import	tsukuba_bunko.peko.Logger;
    34  import tsukuba_bunko.peko.PekoSystem;
    35
    36
    37  /***
    38   * 一度にキャンバスに表示する行のリスト(= ページ)です。
    39   * @author	$Author: ppoi $
    40   * @version	$Revision: 1.5 $
    41   */
    42  public class Page	implements Cloneable, Serializable	{
    43
    44  	/***
    45  	 * serial version UID
    46  	 */
    47  	private static final long	serialVersionUID	= 2116822706503877518L;
    48
    49
    50  	/***
    51  	 * このページを描画するテキストキャンバス
    52  	 */
    53  	transient private TextCanvas	_canvas = null;
    54
    55
    56  	/***
    57  	 * committed lines
    58  	 */
    59  	private List	_committedLines = null;
    60
    61  	/***
    62  	 * コミットされた分のページの高さ
    63  	 */
    64  	private float	_commitedPageHeight = 0f;
    65
    66
    67  	/***
    68  	 * lines
    69  	 */
    70  	transient private List	_lines = null;
    71
    72  	/***
    73  	 * 現在のページの高さ
    74  	 */
    75  	transient private float	_pageHeight = 0f;
    76
    77
    78  	/***
    79  	 * デフォルトフォント
    80  	 */
    81  	transient private Font	_defaultFont = null;
    82
    83  	/***
    84  	 * サイズ
    85  	 */
    86  	private Dimension	_size = new Dimension();
    87
    88  	/***
    89  	 * 位置
    90  	 */
    91  	private Point	_location = new Point( 0, 0 );
    92
    93  	/***
    94  	 * パディング
    95  	 */
    96  	private Insets	_padding = new Insets( 10, 10, 10, 10 );
    97
    98  	/***
    99  	 * 前景色
    100 	 */
    101 	private Color	_foreground = Color.white;
    102
    103 	/***
    104 	 * 影色
    105 	 */
    106 	private Color	_shadow = Color.black;
    107
    108 	/***
    109 	 * 背景色
    110 	 */
    111 	private Color	_background = Color.black;
    112
    113 	/***
    114 	 * 背景の透明度
    115 	 */
    116 	private float	_transparency = 0.5f;
    117
    118
    119 	/***
    120 	 * <code>Page</code> のインスタンスを作成します。
    121 	 */
    122 	public Page()
    123 	{
    124 		super();
    125 	}
    126
    127
    128 	/***
    129 	 * このページを描画するテキストキャンバスを設定します。
    130 	 * @param	canvas	テキストキャンバス
    131 	 */
    132 	void setTextCanvas( TextCanvas canvas )
    133 	{
    134 		_canvas = canvas;
    135 	}
    136
    137 	/***
    138 	 * このページを描画するテキストキャンバスを取得します。
    139 	 * @return	canvas
    140 	 */
    141 	public TextCanvas getTextCanvas()
    142 	{
    143 		return _canvas;
    144 	}
    145
    146
    147 	/***
    148 	 * デフォルトフォントを設定します。
    149 	 * @param	font	デフォルトフォント
    150 	 */
    151 	public void setDefaultFont( Font font )
    152 	{
    153 		_defaultFont = font;
    154 	}
    155
    156 	/***
    157 	 * デフォルトフォントを取得します。
    158 	 * @return	デフォルトフォント
    159 	 */
    160 	public Font getDefaultFont()
    161 	{
    162 		return _defaultFont;
    163 	}
    164
    165 	/***
    166 	 * このページでテキストを描画する際に使用する FontRenderContext を取得します。
    167 	 * @return	描画に使用する FontRenderContext インスタンス
    168 	 */
    169 	public FontRenderContext getFontRenderContext()
    170 	{
    171 		if( _canvas == null )	{
    172 			return null;
    173 		}
    174 		else	{
    175 			return _canvas.getFontRenderContext();
    176 		}
    177 	}
    178
    179 	/***
    180 	 * 表示領域のサイズを設定します。
    181 	 * @param	size	サイズ
    182 	 */
    183 	public void setSize( Dimension size )
    184 	{
    185 		_size.setSize( size );
    186 	}
    187
    188 	/***
    189 	 * 表示領域のサイズを取得します。
    190 	 * @return	表示領域のサイズを格納した Dimension インスタンス
    191 	 */
    192 	public Dimension getSize()
    193 	{
    194 		return getSize( new Dimension() );
    195 	}
    196
    197 	/***
    198 	 * 表示領域のサイズを取得し、<code>d</code> に格納します。
    199 	 * @param	d	表示領域のサイズを格納する Dimension インスタンス
    200 	 * @return	<code>d</code>。<code>d == null</code> の場合は新規に生成された Dimension インスタンス
    201 	 */
    202 	public Dimension getSize( Dimension d )
    203 	{
    204 		if( d == null )	{
    205 			d = new Dimension();
    206 		}
    207 		d.setSize( _size );
    208 		return d;
    209 	}
    210
    211 	/***
    212 	 * 表示領域の位置を設定します。
    213 	 * @param	x	表示領域の左上隅 x 座標
    214 	 * @param	y	表示領域の左上隅 y 座標
    215 	 */
    216 	public void setLocation( int x, int y )
    217 	{
    218 		_location.x = x;
    219 		_location.y = y;
    220 	}
    221
    222 	/***
    223 	 * マージン領域のサイズを取得します。
    224 	 * @return	マージン領域のサイズを格納した Insets インスタンス
    225 	 */
    226 	public Point getMargin()
    227 	{
    228 		return getLocation( null );
    229 	}
    230
    231 	/***
    232 	 * 表示領域の位置を取得し， <code>location</code> に格納します。
    233 	 * @param	location	表示領域の位置を格納する Point インスタンス
    234 	 * @return	<code>location</code>。<code>location == null</code> の場合は新規に生成された Point インスタンス
    235 	 */
    236 	public Point getLocation( Point location )
    237 	{
    238 		if( location == null )	{
    239 			location = (Point)_location.clone();
    240 		}
    241 		else	{
    242 			location.x = _location.x;
    243 			location.y = _location.y;
    244 		}
    245 		return location;
    246 	}
    247
    248 	/***
    249 	 * パディング領域のサイズを設定します。
    250 	 * @param	top	padding-top
    251 	 * @param	left	padding-left
    252 	 * @param	bottom	padding-bottom
    253 	 * @param	right	padding-right
    254 	 */
    255 	public void setPadding( int top, int left, int bottom, int right )
    256 	{
    257 		_padding.top = top;
    258 		_padding.left = left;
    259 		_padding.bottom = bottom;
    260 		_padding.right = right;
    261 	}
    262
    263 	/***
    264 	 * パディング領域のサイズを取得します。
    265 	 * @return	パディング領域のサイズを格納した Insets インスタンス
    266 	 */
    267 	public Insets getPadding()
    268 	{
    269 		return getPadding( null );
    270 	}
    271
    272 	/***
    273 	 * パディング領域のサイズを取得し、<code>padding</code> に格納して返します。
    274 	 * @param	padding	パディング領域のサイズを格納する Insets インスタンス
    275 	 * @return	<code>padding</code>。<code>padding == null</code> の場合は、新規に生成された Insets インスタンス
    276 	 */
    277 	public Insets getPadding( Insets padding )
    278 	{
    279 		if( padding == null )	{
    280 			padding = (Insets)_padding.clone();
    281 		}
    282 		else	{
    283 			padding.top = _padding.top;
    284 			padding.left = _padding.left;
    285 			padding.bottom = _padding.bottom;
    286 			padding.right = _padding.right;
    287 		}
    288 		return padding;
    289 	}
    290
    291 	/***
    292 	 * 前景色を設定します。
    293 	 * @param	foreground	前景色
    294 	 */
    295 	public void setForeground( Color foreground )
    296 	{
    297 		_foreground = foreground;
    298 	}
    299
    300 	/***
    301 	 * 前景色を取得します。
    302 	 * @return	前景色
    303 	 */
    304 	public Color getForeground()
    305 	{
    306 		return _foreground;
    307 	}
    308
    309 	/***
    310 	 * 影色を設定します。
    311 	 * @param	shadow	影色
    312 	 */
    313 	public void setShadow( Color shadow )
    314 	{
    315 		_shadow = shadow;
    316 	}
    317
    318 	/***
    319 	 * 影色を取得します。
    320 	 * @return	影色
    321 	 */
    322 	public Color getShadow()
    323 	{
    324 		return _shadow;
    325 	}
    326
    327 	/***
    328 	 * 背景色を設定します。
    329 	 * @param	background	背景色
    330 	 */
    331 	public void setBackground( Color background )
    332 	{
    333 		_background = background;
    334 	}
    335
    336 	/***
    337 	 * 背景色を取得します。
    338 	 * @return	背景色
    339 	 */
    340 	public Color getBackground()
    341 	{
    342 		return _background;
    343 	}
    344
    345 	/***
    346 	 * 背景色の透明度を設定します.
    347 	 * @param	trans	透明度
    348 	 */
    349 	public void setTransparency( float trans )
    350 	{
    351 		_transparency = trans;
    352 	}
    353
    354 	/***
    355 	 * 背景色の透明度を取得します。
    356 	 * @return	透明度
    357 	 */
    358 	public float getTransparency()
    359 	{
    360 		return _transparency;
    361 	}
    362
    363
    364 	/***
    365 	 * このページで表示可能な行幅の最大値を取得します。
    366 	 * @return	最大行幅
    367 	 */
    368 	public float getMaxLineWidth()
    369 	{
    370 		int	width = _size.width;
    371 		width -= _padding.left;
    372 		width -= _padding.right;
    373
    374 		return (float)width;
    375 	}
    376
    377 	/***
    378 	 * 行を末尾に追加します。
    379 	 * @param	line	追加する行
    380 	 */
    381 	public synchronized void addLine( Line line )
    382 	{
    383 		if( _lines == null )	{
    384 			_lines = new java.util.ArrayList();
    385 		}
    386 		_lines.add( line );
    387 		_pageHeight += line.getAscent();
    388 		_pageHeight += line.getDescent();
    389 	}
    390
    391 	/***
    392 	 * 現在ページに含まれる行数を取得します。
    393 	 * @return	行数
    394 	 */
    395 	public int getLineCount()
    396 	{
    397 		if( _lines != null )	{
    398 			return _lines.size();
    399 		}
    400 		else	{
    401 			return 0;
    402 		}
    403 	}
    404
    405 	/***
    406 	 * <code>index</code> で指定された行を <code>line</code> で置き換えます。
    407 	 * @param	index	置換する行のインデックス
    408 	 * @param	line	新しい行
    409 	 */
    410 	public synchronized void setLine( int index, Line line )
    411 	{
    412 		try	{
    413 			if( (_lines == null) || (index < 0) || (index >= _lines.size()) )	{
    414 				Logger.debug( "[canvas.text] invalid length! index:" + index + " size:" + ((_lines != null)?_lines.size():0) );
    415 			}
    416
    417 			synchronized( this )	{
    418 				Line	old = (Line)_lines.get( index );
    419 				_pageHeight -= (old.getAscent() + old.getDescent());
    420 				_lines.set( index, line );
    421 				_pageHeight += (line.getAscent() + line.getDescent());
    422 			}
    423 		}
    424 		catch( IndexOutOfBoundsException ioobe )	{
    425 			Logger.error( "[canvas] invalid line number.", ioobe );
    426 			throw ioobe;
    427 		}
    428 	}
    429
    430 	/***
    431 	 * <code>index</code> で指定された行をページから削除します。<code>index</code>
    432 	 * より後ろの行は一行ずつ上に詰められます。
    433 	 * @param	index	削除する行のインデックス
    434 	 * @throws	IndexOutOfBoundsException	<code>index</code> が範囲外の場合
    435 	 */
    436 	public void removeLine( int index )
    437 	{
    438 		try	{
    439 			if( _lines == null )	{
    440 				throw new IndexOutOfBoundsException( "there is still no line." );
    441 			}
    442
    443 			synchronized( this )	{
    444 				Line	line = (Line)_lines.remove( index );
    445 				_pageHeight -= (line.getAscent() + line.getDescent());
    446 			}
    447 		}
    448 		catch( IndexOutOfBoundsException ioobe )	{
    449 			Logger.error( "[canvas] invalid line number.", ioobe );
    450 			throw ioobe;
    451 		}
    452 	}
    453
    454 	/***
    455 	 * 行リストを取得します。
    456 	 */
    457 	public List getLines()
    458 	{
    459 		if( _lines != null )	{
    460 			return (List)((java.util.ArrayList)_lines).clone();
    461 		}
    462 		else	{
    463 			return null;
    464 		}
    465 	}
    466
    467 	/***
    468 	 * すべての行をクリアします。
    469 	 */
    470 	public void clearLines()
    471 	{
    472 		synchronized( this )	{
    473 			if( _lines != null )	{
    474 				_lines.clear();
    475 				_pageHeight = 0f;
    476 			}
    477 		}
    478 	}
    479
    480 	/***
    481 	 * <code>line</code> をページに追加可能かどうかを判定します。
    482 	 * @param	line	判定する行
    483 	 * @return	追加可能な場合 <code>true</code>、追加できな場合は <code>false</code>
    484 	 */
    485 	public boolean isAdaptive( Line line )
    486 	{
    487 		if( line == null )	{
    488 			throw new NullPointerException( "てめぇ、なめてんじゃねぇぞぐらぁ！" );
    489 		}
    490 		float	pageHeight = _pageHeight + _padding.top + _padding.bottom;
    491 		return ((pageHeight + line.getAscent() + line.getDescent()) < (float)_size.height);
    492 	}
    493
    494
    495 	/***
    496 	 * このページへの変更をキャンバスに反映させます。
    497 	 */
    498 	public void updateCanvas()
    499 	{
    500 		if( _canvas != null )	{
    501 			_canvas.updateCanvas();
    502 		}
    503 	}
    504
    505 	/***
    506 	 * このページの内容（テキスト）の変更をキャンバスに反映させます。
    507 	 */
    508 	public void updateContents()
    509 	{
    510 		if( _canvas != null )	{
    511 			if( !_canvas.isVisible() )	{
    512 				//非表示だった場合は，300 msec wait する。
    513 				PekoSystem.getInstance().getActionControler().stop( 300L );
    514 			}
    515 			_canvas.updateText();
    516 		}
    517 	}
    518
    519 	/***
    520 	 * 変更をコミットします。
    521 	 */
    522 	public void commit()
    523 	{
    524 		Logger.debug( "[canvas.text] commit." );
    525 		if( _lines != null )	{
    526 			if( _committedLines != null )	{
    527 				_committedLines.clear();
    528 				_committedLines.addAll( _lines );
    529 			}
    530 			else	{
    531 				_committedLines = (List)((java.util.ArrayList)_lines).clone();
    532 			}
    533 			Logger.debug( "[canvas.text] committed lines :" + _committedLines.size() );
    534 		}
    535 		_commitedPageHeight = _pageHeight;
    536 	}
    537
    538 	/***
    539 	 * コミットされていない変更を破棄します。
    540 	 */
    541 	public void rollback()
    542 	{
    543 		Logger.debug( "[canvas.text] rollback." );
    544 		if( _lines != null )	{
    545 			_lines.clear();
    546 		}
    547 		_lines = _committedLines;
    548 		_committedLines = null;
    549 		_pageHeight = _commitedPageHeight;
    550 	}
    551
    552
    553 //
    554 //	Clonable の実装
    555 //
    556 	public Object clone()
    557 	{
    558 		return clone( new Page() );
    559 	}
    560
    561 	/***
    562 	 * <code>page</code> をこのページのクローンとします。
    563 	 * @param	copy	このページのクローンにする Page インスタンス
    564 	 * @return	<code>copy</code>
    565 	 */
    566 	public Object clone( Page copy )
    567 	{
    568 		synchronized( this )	{
    569 			if( _lines != null )	{
    570 				copy._lines = (List)((java.util.ArrayList)_lines).clone();
    571 			}
    572 		}
    573 		copy._defaultFont = _defaultFont;
    574 		copy._size = (Dimension)_size.clone();
    575 		copy._location = (Point)_location.clone();
    576 		copy._padding = (Insets)_padding.clone();
    577 		copy._foreground = _foreground;
    578 		copy._background = _background;
    579 		copy._transparency = _transparency;
    580
    581 		return copy;
    582 	}
    583 }