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 }