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: CanvasManager.java,v 1.3 2005/07/23 17:34:52 ppoi Exp $
18   */
19  package tsukuba_bunko.peko.canvas;
20  
21  import	java.awt.Color;
22  import	java.awt.Dimension;
23  import	java.awt.Font;
24  
25  import	java.awt.font.TextAttribute;
26  
27  import	java.io.Serializable;
28  
29  import	java.util.List;
30  import	java.util.Map;
31  
32  import	javax.swing.ImageIcon;
33  import	javax.swing.JComponent;
34  import	javax.swing.JFrame;
35  
36  import	tsukuba_bunko.peko.ActionControler;
37  import	tsukuba_bunko.peko.Logger;
38  import	tsukuba_bunko.peko.PekoSystem;
39  
40  import	tsukuba_bunko.peko.canvas.select.SelectCanvas;
41  import	tsukuba_bunko.peko.canvas.select.SelectItem;
42  import	tsukuba_bunko.peko.canvas.select.SelectItemButton;
43  
44  import	tsukuba_bunko.peko.canvas.stage.Stage;
45  import	tsukuba_bunko.peko.canvas.stage.StageCanvas;
46  
47  import	tsukuba_bunko.peko.canvas.text.Page;
48  import	tsukuba_bunko.peko.canvas.text.TextCanvas;
49  
50  import	tsukuba_bunko.peko.resource.ResourceManager;
51  import	tsukuba_bunko.peko.resource.FontManager;
52  
53  import	tsukuba_bunko.peko.session.Session;
54  
55  
56  /***
57   * Canvas を管理する機能を提供します。
58   * @author	$Author: ppoi $
59   * @version	$Revision: 1.3 $
60   */
61  public class CanvasManager	{
62  
63  	/***
64  	 * テキストキャンバス
65  	 */
66  	private TextCanvas	_text = null;
67  
68  	/***
69  	 * ステージキャンバス
70  	 */
71  	private StageCanvas	_stage = null;
72  
73  	/***
74  	 * 選択肢キャンバス
75  	 */
76  	private SelectCanvas	_select = null;
77  
78  
79  	/***
80  	 * テキストの履歴
81  	 */
82  	private List	_history = null;
83  
84  	/***
85  	 * テキストの履歴の最大数
86  	 */
87  	private int	_maxHistoryCount = 0;
88  
89  	/***
90  	 * 現在の Page
91  	 */
92  	private Page	_currentPage = null;
93  
94  	/***
95  	 * 現在選択肢を表示中かどうか
96  	 */
97  	private boolean	_selecting = false;
98  
99  
100 
101 	/***
102 	 * 選択肢ボタンスタイル
103 	 */
104 	private Map	_selectStyle = null;
105 
106 	/***
107 	 * タイトルメニューボタンスタイル
108 	 */
109 	private Map	_titleStyle = null;
110 
111 
112 	/***
113 	 * <code>CanvasManager</code> のインスタンスを作成します。
114 	 */
115 	public CanvasManager()
116 	{
117 		super();
118 	}
119 
120 
121 	/***
122 	 * 初期化します。
123 	 */
124 	public void initialize()
125 	{
126 		PekoSystem	system = PekoSystem.getInstance();
127 		ResourceManager	resources = ResourceManager.getInstance();
128 
129 		_history = new java.util.ArrayList();
130 
131 		JFrame	mainWindow = system.getMainWindow();
132 
133 		String	title = (String)resources.getResource( "game-info.title" );
134 		Dimension	canvasSize = (Dimension)resources.getResource( ResourceIDs.CANVAS_SIZE );
135 		ImageIcon	icon = (ImageIcon)resources.getResource( "game-info.icon" );
136 
137 		mainWindow.setTitle( title );
138 		if( (icon.getIconHeight() > 0) && (icon.getIconWidth() > 0) )	{
139 			mainWindow.setIconImage( icon.getImage() );
140 		}
141 
142 		mainWindow.setResizable( true );
143 		JComponent	contentPane = (JComponent)mainWindow.getContentPane();
144 		contentPane.setPreferredSize( canvasSize );
145 		contentPane.setSize( canvasSize );
146 		contentPane.setLayout( null );
147 
148 		_stage = new StageCanvas();
149 		_stage.setStage( new Stage() );
150 		contentPane.add( _stage );
151 		_stage.setLocation( 0, 0 );
152 
153 		_text = new TextCanvas();
154 		_text.setPreferredSize( canvasSize );
155 		_text.setSize( canvasSize );
156 		_text.setVisible( false );
157 		_stage.add( _text );
158 		_text.setLocation( 0, 0 );
159 
160 		_select = new SelectCanvas();
161 		_select.setPreferredSize( canvasSize );
162 		_select.setSize( canvasSize );
163 		_select.setVisible( false );
164 		_stage.add( _select );
165 		_select.setLocation( 0, 0 );
166 		mainWindow.addKeyListener( _select );
167 
168 		Integer	maxHistory = (Integer)resources.getResource( ResourceIDs.CANVAS_PAGE_HISTORY );
169 		if( maxHistory == null )	{
170 			_maxHistoryCount = 10;
171 		}
172 		else	{
173 			_maxHistoryCount = maxHistory.intValue();
174 		}
175 
176 		initializeSelectStyle();
177 		initializeTitleStyle();
178 	}
179 
180 	/***
181 	 * 選択肢のスタイルを設定します。
182 	 */
183 	protected void initializeSelectStyle()
184 	{
185 		ResourceManager	resources = ResourceManager.getInstance();
186 
187 		_selectStyle = new java.util.HashMap( 17 );
188 
189 		Color	colorValue = (Color)resources.getResource( ResourceIDs.SELECT_BUTTON_BACKGROUND_COLOR );
190 		if( colorValue == null )	{
191 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_COLOR, "black"} );
192 			colorValue = Color.black;
193 		}
194 		_selectStyle.put( SelectItemButton.STYLE_BACKGROUND_COLOR, colorValue );
195 
196 		Float	floatValue = (Float)resources.getResource( ResourceIDs.SELECT_BUTTON_BACKGROUND_TRANSPARENCY );
197 		if( floatValue == null )	{
198 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, "0.5f"} );
199 			floatValue = new Float( 0.5f );
200 		}
201 		else if( floatValue.floatValue() < 0f )	{
202 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, "0.5f"} );
203 			floatValue = new Float( 0.5f );
204 		}
205 		_selectStyle.put( SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, floatValue );
206 
207 		Integer	intValue = (Integer)resources.getResource( ResourceIDs.SELECT_BUTTON_WIDTH );
208 		if( intValue == null )	{
209 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_WIDTH, "320"} );
210 			intValue = new Integer( 320 );
211 		}
212 		_selectStyle.put( SelectItemButton.STYLE_WIDTH, intValue );
213 
214 		colorValue = (Color)resources.getResource( ResourceIDs.SELECT_BUTTON_FOREGROUND_SELECTED );
215 		if( colorValue == null )	{
216 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_SELECTED, "white"} );
217 			colorValue = Color.white;
218 		}
219 		_selectStyle.put( SelectItemButton.STYLE_FOREGROUND_SELECTED, colorValue );
220 
221 		colorValue = (Color)resources.getResource( ResourceIDs.SELECT_BUTTON_FOREGROUND_UNSELECTED );
222 		if( colorValue == null )	{
223 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_UNSELECTED, "darkGray"} );
224 			colorValue = Color.darkGray;
225 		}
226 		_selectStyle.put( SelectItemButton.STYLE_FOREGROUND_UNSELECTED, colorValue );
227 
228 		colorValue = (Color)resources.getResource( ResourceIDs.SELECT_BUTTON_FOREGROUND_SHADOW );
229 		if( colorValue == null )	{
230 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_SHADOW, "black"} );
231 			colorValue = Color.black;
232 		}
233 		_selectStyle.put( SelectItemButton.STYLE_FOREGROUND_SHADOW, colorValue );
234 
235 		Font	fontValue = (Font)resources.getResource( ResourceIDs.SELECT_BUTTON_FONT );
236 		if( fontValue == null )	{
237 			Map	attributes = new java.util.HashMap( 17 );
238 			attributes.put( TextAttribute.FAMILY, "SansSerif" );
239 			attributes.put( TextAttribute.SIZE, new Float(16f) );
240 			fontValue = FontManager.getInstance().getFont( attributes );
241 		}
242 		_selectStyle.put( SelectItemButton.STYLE_FONT, fontValue );
243 	}
244 
245 
246 	/***
247 	 * タイトルメニューのスタイルを設定します。
248 	 */
249 	protected void initializeTitleStyle()
250 	{
251 		ResourceManager	resources = ResourceManager.getInstance();
252 
253 		_titleStyle = new java.util.HashMap( 17 );
254 
255 		Color	colorValue = (Color)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_BACKGROUND_COLOR );
256 		if( colorValue == null )	{
257 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_COLOR, "black"} );
258 			colorValue = Color.black;
259 		}
260 		_titleStyle.put( SelectItemButton.STYLE_BACKGROUND_COLOR, colorValue );
261 
262 		Float	floatValue = (Float)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_BACKGROUND_TRANSPARENCY );
263 		if( floatValue == null )	{
264 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, "0.5f"} );
265 			floatValue = new Float( 0.5f );
266 		}
267 		else if( floatValue.floatValue() < 0f )	{
268 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, "0.5f"} );
269 			floatValue = new Float( 0.5f );
270 		}
271 		_titleStyle.put( SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, floatValue );
272 
273 		Integer	intValue = (Integer)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_WIDTH );
274 		if( intValue == null )	{
275 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_WIDTH, "320"} );
276 			intValue = new Integer( 320 );
277 		}
278 		_titleStyle.put( SelectItemButton.STYLE_WIDTH, intValue );
279 
280 		colorValue = (Color)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_FOREGROUND_SELECTED );
281 		if( colorValue == null )	{
282 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_SELECTED, "white"} );
283 			colorValue = Color.white;
284 		}
285 		_titleStyle.put( SelectItemButton.STYLE_FOREGROUND_SELECTED, colorValue );
286 
287 		colorValue = (Color)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_FOREGROUND_UNSELECTED );
288 		if( colorValue == null )	{
289 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_UNSELECTED, "darkGray"} );
290 			colorValue = Color.darkGray;
291 		}
292 		_titleStyle.put( SelectItemButton.STYLE_FOREGROUND_UNSELECTED, colorValue );
293 
294 		colorValue = (Color)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_FOREGROUND_SHADOW );
295 		if( colorValue == null )	{
296 			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_SHADOW, "black"} );
297 			colorValue = Color.black;
298 		}
299 		_titleStyle.put( SelectItemButton.STYLE_FOREGROUND_SHADOW, colorValue );
300 
301 		Font	fontValue = (Font)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_FONT );
302 		if( fontValue == null )	{
303 			Map	attributes = new java.util.HashMap( 17 );
304 			attributes.put( TextAttribute.FAMILY, "SansSerif" );
305 			attributes.put( TextAttribute.SIZE, new Float(16f) );
306 			fontValue = FontManager.getInstance().getFont( attributes );
307 		}
308 		_titleStyle.put( SelectItemButton.STYLE_FONT, fontValue );
309 	}
310 
311 	/***
312 	 * テキストキャンバスを取得します。
313 	 * @return	テキストキャンバス
314 	 */
315 	public TextCanvas getTextCanvas()
316 	{
317 		return _text;
318 	}
319 
320 	/***
321 	 * ステージキャンバスを取得します。
322 	 * @return	ステージキャンバス
323 	 */
324 	public StageCanvas getStageCanvas()
325 	{
326 		return _stage;
327 	}
328 
329 	/***
330 	 * ステージを取得します。
331 	 */
332 	public Stage getStage()
333 	{
334 		return _stage.getStage();
335 	}
336 
337 	/***
338 	 * 現在のページを取得します。
339 	 */
340 	public Page getCurrentPage()
341 	{
342 		return _text.getPage();
343 	}
344 
345 	/***
346 	 * 次の新しいページに移動します。
347 	 * @return	現在のページ(移動後)
348 	 */
349 	public Page advancesNewPage()
350 	{
351 		Page	page = _text.getPage();
352 		if( page != null )	{
353 			synchronized( page )	{
354 				putTextHistory( page );
355 				page.clearLines();
356 			}
357 		}
358 		else	{
359 			page = new Page();
360 			_text.setPage( page );
361 		}
362 
363 		_currentPage = page;
364 		return page;
365 	}
366 
367 	/***
368 	 * <code>page</code> をテキストの履歴に追加します。
369 	 * @param	page	履歴に追加するページ
370 	 */
371 	protected void putTextHistory( Page page )
372 	{
373 		if( page.getLineCount() == 0 )	{
374 			//	空白ページは履歴に入れないデス
375 			return;
376 		}
377 
378 		Page	previous = null;
379 		if( _history.size() >= _maxHistoryCount )	{
380 			previous = (Page)_history.remove( 0 );
381 			page.clone( previous );
382 		}
383 		else	{
384 			previous = (Page)page.clone();
385 		}
386 		_history.add( previous );
387 	}
388 
389 	/***
390 	 * 過去の文章を表示します。
391 	 * @param	index	戻るページ数。
392 	 * @return	次があれば true
393 	 */
394 	public boolean readAgain( int index )
395 	{
396 		if( _selecting )	{
397 			_select.setVisible( false );
398 		}
399 
400 		Page	previous = (Page)_history.get( _history.size() - index );
401 		_text.setPage( previous );
402 		_text.updateCanvas();
403 		_text.updateText();
404 		return ((_history.size() - index) > 0);
405 	}
406 
407 	/***
408 	 * 現在のページに戻ります。
409 	 */
410 	public void returnCurrent()
411 	{
412 		_text.setPage( _currentPage );
413 		_text.updateCanvas();
414 		_text.updateText();
415 
416 		if( _selecting )	{
417 			hideTextCanvas();
418 			_select.setVisible( true );
419 		}
420 	}
421 
422 	/***
423 	 * 履歴として保存されている過去のページ数を取得します。
424 	 * @return	履歴として保存されている過去のページ数
425 	 */
426 	public int getPageHistoryCount()
427 	{
428 		return _history.size();
429 	}
430 
431 	/***
432 	 * 現在選択肢を表示中かどうかを取得します。
433 	 * @return	選択肢表示中の場合 <code>true</code>
434 	 */
435 	public boolean isShowingSelect()
436 	{
437 		return _selecting;
438 	}
439 
440 	/***
441 	 * 選択肢を表示します。
442 	 * @param	selectItems	選択肢リスト
443 	 * @return	選択された選択肢の ID
444 	 */
445 	public String showSelect( List selectItems )
446 	{
447 		ResourceManager	resources = ResourceManager.getInstance();
448 
449 		String	alignment = (String)resources.getResource( ResourceIDs.SELECT_ALIGN );
450 		if( alignment == null )	{
451 			Logger.warn( MessageIDs.CVS3001W, new Object[]{"center"} );
452 			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
453 		}
454 		else if( "center".equalsIgnoreCase(alignment) )	{
455 			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
456 		}
457 		else if( "left".equalsIgnoreCase(alignment) )	{
458 			_select.setAlignment( SelectCanvas.ALIGN_LEFT );
459 		}
460 		else if( "right".equalsIgnoreCase(alignment) )	{
461 			_select.setAlignment( SelectCanvas.ALIGN_RIGHT );
462 		}
463 		else	{
464 			Logger.warn( MessageIDs.CVS3001W, new Object[]{"center"} );
465 			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
466 		}
467 
468 		String	valign = (String)resources.getResource( ResourceIDs.SELECT_VERTICAL_ALIGN );
469 		if( valign == null )	{
470 			Logger.warn( MessageIDs.CVS3006W, new Object[]{"middle"} );
471 			_select.setVerticalAlignment( SelectCanvas.VALIGN_MIDDLE );
472 		}
473 		else if( "top".equalsIgnoreCase(valign) )	{
474 			_select.setVerticalAlignment( SelectCanvas.VALIGN_TOP );
475 		}
476 		else if( "middle".equalsIgnoreCase(valign) )	{
477 			_select.setVerticalAlignment( SelectCanvas.VALIGN_MIDDLE );
478 		}
479 		else if( "bottom".equalsIgnoreCase(valign) )	{
480 			_select.setVerticalAlignment( SelectCanvas.VALIGN_BOTTOM );
481 		}
482 		else	{
483 			Logger.warn( MessageIDs.CVS3006W, new Object[]{"middle"} );
484 			_select.setVerticalAlignment( SelectCanvas.VALIGN_MIDDLE );
485 		}
486 
487 		Integer	columns = (Integer)resources.getResource( ResourceIDs.SELECT_COLUMNS );
488 		if( columns == null )	{
489 			Logger.warn( MessageIDs.CVS3002W, new Object[]{"1"} );
490 			_select.setColumns( 1 );
491 		}
492 		else	{
493 			_select.setColumns( columns.intValue() );
494 		}
495 
496 		Integer	span = (Integer)resources.getResource( ResourceIDs.SELECT_SPAN_COLUMN );
497 		if( span == null )	{
498 			Logger.warn( MessageIDs.CVS3004W, new Object[]{"5"} );
499 			_select.setColumnSpan( 5 );
500 		}
501 		else	{
502 			_select.setColumnSpan( span.intValue() );
503 		}
504 
505 		span = (Integer)resources.getResource( ResourceIDs.SELECT_SPAN_ROW );
506 		if( span == null )	{
507 			Logger.warn( MessageIDs.CVS3005W, new Object[]{"5"} );
508 			_select.setRowSpan( 5 );
509 		}
510 		else	{
511 			_select.setRowSpan( span.intValue() );
512 		}
513 
514 		span = (Integer)resources.getResource( ResourceIDs.SELECT_SPAN_BOUND );
515 		if( span == null )	{
516 			Logger.warn( MessageIDs.CVS3007W, new Object[]{"20"} );
517 			_select.setBoundSpan( 20 );
518 		}
519 		else	{
520 			_select.setBoundSpan( span.intValue() );
521 		}
522 
523 		_select.setButtonStyle( _selectStyle );
524 
525 		if( _text.isVisible() )	{
526 			hideTextCanvas();
527 		}
528 
529 		Page	page = advancesNewPage();
530 		page.commit();
531 
532 		_selecting = true;
533 
534 		ActionControler	controler = PekoSystem.getInstance().getActionControler();
535 		if( controler.getPlayMode() == ActionControler.PM_SKIP )	{
536 			controler.setPlayModeToNormal();
537 		}
538 
539 		_select.setVisible( true );
540 		String	id = _select.select( selectItems );
541 		_select.setVisible( false );
542 
543 		_selecting = false;
544 
545 		return id;
546 	}
547 
548 	/***
549 	 * タイトル画面を描画します。
550 	 * @param	showTitle	オープニングを表示するかどうか
551 	 */
552 	public String showTitle( boolean showTitle )
553 	{
554 		ResourceManager	resources = ResourceManager.getInstance();
555 
556 		String	alignment = (String)resources.getResource( ResourceIDs.TITLE_MENU_ALIGN );
557 		if( alignment == null )	{
558 			Logger.warn( MessageIDs.CVS3001W, new Object[]{"center"} );
559 			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
560 		}
561 		else if( "center".equalsIgnoreCase(alignment) )	{
562 			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
563 		}
564 		else if( "left".equalsIgnoreCase(alignment) )	{
565 			_select.setAlignment( SelectCanvas.ALIGN_LEFT );
566 		}
567 		else if( "right".equalsIgnoreCase(alignment) )	{
568 			_select.setAlignment( SelectCanvas.ALIGN_RIGHT );
569 		}
570 		else	{
571 			Logger.warn( MessageIDs.CVS3001W, new Object[]{"center"} );
572 			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
573 		}
574 
575 		String	valign = (String)resources.getResource( ResourceIDs.TITLE_MENU_VERTICAL_ALIGN );
576 		if( valign == null )	{
577 			Logger.warn( MessageIDs.CVS3006W, new Object[]{"bottom"} );
578 			_select.setVerticalAlignment( SelectCanvas.VALIGN_BOTTOM );
579 		}
580 		else if( "top".equalsIgnoreCase(valign) )	{
581 			_select.setVerticalAlignment( SelectCanvas.VALIGN_TOP );
582 		}
583 		else if( "middle".equalsIgnoreCase(valign) )	{
584 			_select.setVerticalAlignment( SelectCanvas.VALIGN_MIDDLE );
585 		}
586 		else if( "bottom".equalsIgnoreCase(valign) )	{
587 			_select.setVerticalAlignment( SelectCanvas.VALIGN_BOTTOM );
588 		}
589 		else	{
590 			Logger.warn( MessageIDs.CVS3006W, new Object[]{"bottom"} );
591 			_select.setVerticalAlignment( SelectCanvas.VALIGN_BOTTOM );
592 		}
593 
594 		Integer	columns = (Integer)resources.getResource( ResourceIDs.TITLE_MENU_COLUMNS );
595 		if( columns == null )	{
596 			Logger.warn( MessageIDs.CVS3002W, new Object[]{"1"} );
597 			_select.setColumns( 1 );
598 		}
599 		else	{
600 			_select.setColumns( columns.intValue() );
601 		}
602 
603 		String	startCaption = (String)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_CAPTION_START );
604 		if( startCaption == null )	{
605 			startCaption = "Start";
606 			Logger.warn( MessageIDs.CVS4001W, new Object[]{"start", startCaption} );
607 		}
608 		String	resumeCaption = (String)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_CAPTION_RESUME );
609 		if( resumeCaption == null )	{
610 			resumeCaption = "Load";
611 			Logger.warn( MessageIDs.CVS4001W, new Object[]{"resume", resumeCaption} );
612 		}
613 		String	exitCaption = (String)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_CAPTION_EXIT );
614 		if( exitCaption == null )	{
615 			exitCaption = "Exit";
616 			Logger.warn( MessageIDs.CVS4001W, new Object[]{"exit", exitCaption} );
617 		}
618 
619 		_select.setButtonStyle( _titleStyle );
620 
621 		Integer	span = (Integer)resources.getResource( ResourceIDs.TITLE_MENU_SPAN_COLUMN );
622 		if( span == null )	{
623 			Logger.warn( MessageIDs.CVS3004W, new Object[]{"5"} );
624 			_select.setColumnSpan( 5 );
625 		}
626 		else	{
627 			_select.setColumnSpan( span.intValue() );
628 		}
629 
630 		span = (Integer)resources.getResource( ResourceIDs.TITLE_MENU_SPAN_ROW );
631 		if( span == null )	{
632 			Logger.warn( MessageIDs.CVS3005W, new Object[]{"5"} );
633 			_select.setRowSpan( 5 );
634 		}
635 		else	{
636 			_select.setRowSpan( span.intValue() );
637 		}
638 
639 		span = (Integer)resources.getResource( ResourceIDs.TITLE_MENU_SPAN_BOUND );
640 		if( span == null )	{
641 			Logger.warn( MessageIDs.CVS3007W, new Object[]{"20"} );
642 			_select.setBoundSpan( 20 );
643 		}
644 		else	{
645 			_select.setBoundSpan( span.intValue() );
646 		}
647 
648 
649 		List	items = new java.util.ArrayList( 3 );
650 		SelectItem	item = new SelectItem();
651 		item.setID( "start" );
652 		item.setText( startCaption );
653 		items.add( item );
654 		item = new SelectItem();
655 		item.setID( "resume" );
656 		item.setText( resumeCaption );
657 		items.add( item );
658 		item = new SelectItem();
659 		item.setID( "exit" );
660 		item.setText( exitCaption );
661 		items.add( item );
662 
663 		if( showTitle )	{
664 			String	imageName = (String)resources.getResource( ResourceIDs.TITLE_IMAGE );
665 			if( (imageName != null) && (imageName.length() > 0) )	{
666 				_stage.getStage().setBackgroundImage( imageName );
667 			}
668 			else	{
669 				_stage.getStage().setBackgroundColor( "white" );
670 			}
671 			_stage.updateCanvas( "mofing" );
672 
673 			String	bgmName = (String)resources.getResource( ResourceIDs.OPENING_BGM, true );
674 			if( (bgmName != null) && (bgmName.length() > 0) )	{
675 				Logger.debug( "playBGM: " + bgmName );
676 				_stage.getStage().getAudioPlayer().playBGM( "opening", bgmName, true );
677 			}
678 		}
679 
680 		hideTextCanvas();
681 
682 		_selecting = true;
683 		_select.setVisible( true );
684 		String	id = _select.select( items );
685 		_select.setVisible( false );
686 		_selecting = false;
687 
688 		return id;
689 	}
690 
691 
692 	/***
693 	 * テキストキャンバスを隠します。
694 	 */
695 	public void hideTextCanvas()
696 	{
697 		_text.setVisible( false );
698 		_stage.paintPageBackground( false );
699 	}
700 
701 	/***
702 	 * テキストキャンバスを表示します。
703 	 */
704 	public void showTextCanvas()
705 	{
706 		_stage.paintPageBackground( true );
707 		_text.setVisible( true );
708 	}
709 
710 
711 	/***
712 	 * キャンバスを全てクリアし、初期状態に戻します。
713 	 */
714 	public synchronized void clearAll()
715 	{
716 		Logger.debug( "[canvas] clear All." );
717 		_select.setVisible( false );
718 		hideTextCanvas();
719 //		_text.setVisible( false );
720 		_select.cancel();
721 		_stage.getStage().getAudioPlayer().stopAll();
722 		advancesNewPage();
723 		_text.getPage().commit();
724 		_history.clear();
725 		Stage	stage = _stage.getStage();
726 		stage.exitAll();
727 		stage.setBackgroundColor( "black" );
728 		stage.hideSlide();
729 		_stage.updateCanvas( "mofing" );
730 		stage.commit();
731 	}
732 
733 
734 	/***
735 	 * <code>serializableForm</code> に格納された状態を復元します。
736 	 * @param	session	状態を格納したオブジェクト
737 	 */
738 	public void resume( Session session )
739 	{
740 		Stage	stage = _stage.getStage();
741 		stage.setBackgroundColor( "black" );
742 		stage.updateCanvas( "mofing" );
743 		_stage.setVisible( false );
744 
745 		try	{
746 			SerializableForm	form = (SerializableForm)session.getSessionAttribute( "canvasManager" );
747 			_text.setPage( form.page );
748 			_stage.setStage( form.stage );
749 			form.stage.prepare();
750 			form.page.rollback();
751 		}
752 		catch( Throwable th )	{
753 			Logger.fatal( "[canvas] unsupported serializable form.", th );
754 		}
755 
756 		_stage.setVisible( true );
757 		_stage.getStage().getAudioPlayer().prepare();
758 	}
759 
760 	/***
761 	 * 状態保存用のオブジェクトを取得します。
762 	 * @return	状態を格納したオブジェクト
763 	 */
764 	public void saveState( Session session )
765 	{
766 		SerializableForm	serializable = new SerializableForm();
767 		serializable.page = _text.getPage();
768 		serializable.stage = _stage.getStage();
769 		session.setSessionAttribute( "canvasManager", serializable );
770 	}
771 
772 
773 
774 	/***
775 	 * Canvas の状態を保持します。
776 	 */
777 	public static class SerializableForm	implements Serializable	{
778 
779 		/***
780 		 * serial version UID
781 		 */
782 		private static final long	serialVersionUID	= 7595927208130407689L;
783 
784 		/***
785 		 * Stage
786 		 */
787 		public Stage	stage = null;
788 
789 		/***
790 		 * Page
791 		 */
792 		public Page	page = null;
793 	}
794 }