1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
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
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 }