/*
 * "Peko" Visual Novel System
 *
 * All Rights Reserved.
 * Copyright (c) 1999-2003 Tsukuba Bunko.
 *
 * $Id: CanvasManager.java,v 1.1.2.2 2003/12/28 12:24:50 ppoi Exp $
 */
package tsukuba_bunko.peko.canvas;

import	java.awt.Color;
import	java.awt.Dimension;
import	java.awt.Font;

import	java.awt.font.TextAttribute;

import	java.io.Serializable;

import	java.util.List;
import	java.util.Map;

import	javax.swing.ImageIcon;
import	javax.swing.JComponent;
import	javax.swing.JFrame;

import	tsukuba_bunko.peko.ActionControler;
import	tsukuba_bunko.peko.Logger;
import	tsukuba_bunko.peko.PekoSystem;

import	tsukuba_bunko.peko.canvas.select.SelectCanvas;
import	tsukuba_bunko.peko.canvas.select.SelectItem;
import	tsukuba_bunko.peko.canvas.select.SelectItemButton;

import	tsukuba_bunko.peko.canvas.stage.Stage;
import	tsukuba_bunko.peko.canvas.stage.StageCanvas;

import	tsukuba_bunko.peko.canvas.text.Page;
import	tsukuba_bunko.peko.canvas.text.TextCanvas;

import	tsukuba_bunko.peko.resource.ResourceManager;
import	tsukuba_bunko.peko.resource.FontManager;

import	tsukuba_bunko.peko.session.Session;


/**
 * Canvas を管理する機能を提供します。
 * @author	$Author: ppoi $
 * @version	$Revision: 1.1.2.2 $
 */
public class CanvasManager	{

	/**
	 * テキストキャンバス
	 */
	private TextCanvas	_text = null;

	/**
	 * ステージキャンバス
	 */
	private StageCanvas	_stage = null;

	/**
	 * 選択肢キャンバス
	 */
	private SelectCanvas	_select = null;


	/**
	 * テキストの履歴
	 */
	private List	_history = null;

	/**
	 * テキストの履歴の最大数
	 */
	private int	_maxHistoryCount = 0;

	/**
	 * 現在の Page
	 */
	private Page	_currentPage = null;

	/**
	 * 現在選択肢を表示中かどうか
	 */
	private boolean	_selecting = false;



	/**
	 * 選択肢ボタンスタイル
	 */
	private Map	_selectStyle = null;

	/**
	 * タイトルメニューボタンスタイル
	 */
	private Map	_titleStyle = null;


	/**
	 * <code>CanvasManager</code> のインスタンスを作成します。
	 */
	public CanvasManager()
	{
		super();
	}


	/**
	 * 初期化します。
	 */
	public void initialize()
	{
		PekoSystem	system = PekoSystem.getInstance();
		ResourceManager	resources = ResourceManager.getInstance();

		_history = new java.util.ArrayList();

		JFrame	mainWindow = system.getMainWindow();

		String	title = (String)resources.getResource( "game-info.title" );
		Dimension	canvasSize = (Dimension)resources.getResource( ResourceIDs.CANVAS_SIZE );
		ImageIcon	icon = (ImageIcon)resources.getResource( "game-info.icon" );

		mainWindow.setTitle( title );
		if( (icon.getIconHeight() > 0) && (icon.getIconWidth() > 0) )	{
			mainWindow.setIconImage( icon.getImage() );
		}

		mainWindow.setResizable( true );
		JComponent	contentPane = (JComponent)mainWindow.getContentPane();
		contentPane.setPreferredSize( canvasSize );
		contentPane.setSize( canvasSize );
		contentPane.setLayout( null );

		_stage = new StageCanvas();
		_stage.setStage( new Stage() );
		contentPane.add( _stage );
		_stage.setLocation( 0, 0 );

		_text = new TextCanvas();
		_text.setPreferredSize( canvasSize );
		_text.setSize( canvasSize );
		_text.setVisible( false );
		_stage.add( _text );
		_text.setLocation( 0, 0 );

		_select = new SelectCanvas();
		_select.setPreferredSize( canvasSize );
		_select.setSize( canvasSize );
		_select.setVisible( false );
		_stage.add( _select );
		_select.setLocation( 0, 0 );
		mainWindow.addKeyListener( _select );

		Integer	maxHistory = (Integer)resources.getResource( ResourceIDs.CANVAS_PAGE_HISTORY );
		if( maxHistory == null )	{
			_maxHistoryCount = 10;
		}
		else	{
			_maxHistoryCount = maxHistory.intValue();
		}

		initializeSelectStyle();
		initializeTitleStyle();
	}

	/**
	 * 選択肢のスタイルを設定します。
	 */
	protected void initializeSelectStyle()
	{
		ResourceManager	resources = ResourceManager.getInstance();

		_selectStyle = new java.util.HashMap( 17 );

		Color	colorValue = (Color)resources.getResource( ResourceIDs.SELECT_BUTTON_BACKGROUND_COLOR );
		if( colorValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_COLOR, "black"} );
			colorValue = Color.black;
		}
		_selectStyle.put( SelectItemButton.STYLE_BACKGROUND_COLOR, colorValue );

		Float	floatValue = (Float)resources.getResource( ResourceIDs.SELECT_BUTTON_BACKGROUND_TRANSPARENCY );
		if( floatValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, "0.5f"} );
			floatValue = new Float( 0.5f );
		}
		else if( floatValue.floatValue() < 0f )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, "0.5f"} );
			floatValue = new Float( 0.5f );
		}
		_selectStyle.put( SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, floatValue );

		Integer	intValue = (Integer)resources.getResource( ResourceIDs.SELECT_BUTTON_WIDTH );
		if( intValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_WIDTH, "320"} );
			intValue = new Integer( 320 );
		}
		_selectStyle.put( SelectItemButton.STYLE_WIDTH, intValue );

		colorValue = (Color)resources.getResource( ResourceIDs.SELECT_BUTTON_FOREGROUND_SELECTED );
		if( colorValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_SELECTED, "white"} );
			colorValue = Color.white;
		}
		_selectStyle.put( SelectItemButton.STYLE_FOREGROUND_SELECTED, colorValue );

		colorValue = (Color)resources.getResource( ResourceIDs.SELECT_BUTTON_FOREGROUND_UNSELECTED );
		if( colorValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_UNSELECTED, "darkGray"} );
			colorValue = Color.darkGray;
		}
		_selectStyle.put( SelectItemButton.STYLE_FOREGROUND_UNSELECTED, colorValue );

		colorValue = (Color)resources.getResource( ResourceIDs.SELECT_BUTTON_FOREGROUND_SHADOW );
		if( colorValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_SHADOW, "black"} );
			colorValue = Color.black;
		}
		_selectStyle.put( SelectItemButton.STYLE_FOREGROUND_SHADOW, colorValue );

		Font	fontValue = (Font)resources.getResource( ResourceIDs.SELECT_BUTTON_FONT );
		if( fontValue == null )	{
			Map	attributes = new java.util.HashMap( 17 );
			attributes.put( TextAttribute.FAMILY, "SansSerif" );
			attributes.put( TextAttribute.SIZE, new Float(16f) );
			fontValue = FontManager.getInstance().getFont( attributes );
		}
		_selectStyle.put( SelectItemButton.STYLE_FONT, fontValue );
	}


	/**
	 * タイトルメニューのスタイルを設定します。
	 */
	protected void initializeTitleStyle()
	{
		ResourceManager	resources = ResourceManager.getInstance();

		_titleStyle = new java.util.HashMap( 17 );

		Color	colorValue = (Color)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_BACKGROUND_COLOR );
		if( colorValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_COLOR, "black"} );
			colorValue = Color.black;
		}
		_titleStyle.put( SelectItemButton.STYLE_BACKGROUND_COLOR, colorValue );

		Float	floatValue = (Float)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_BACKGROUND_TRANSPARENCY );
		if( floatValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, "0.5f"} );
			floatValue = new Float( 0.5f );
		}
		else if( floatValue.floatValue() < 0f )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, "0.5f"} );
			floatValue = new Float( 0.5f );
		}
		_titleStyle.put( SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY, floatValue );

		Integer	intValue = (Integer)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_WIDTH );
		if( intValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_WIDTH, "320"} );
			intValue = new Integer( 320 );
		}
		_titleStyle.put( SelectItemButton.STYLE_WIDTH, intValue );

		colorValue = (Color)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_FOREGROUND_SELECTED );
		if( colorValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_SELECTED, "white"} );
			colorValue = Color.white;
		}
		_titleStyle.put( SelectItemButton.STYLE_FOREGROUND_SELECTED, colorValue );

		colorValue = (Color)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_FOREGROUND_UNSELECTED );
		if( colorValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_UNSELECTED, "darkGray"} );
			colorValue = Color.darkGray;
		}
		_titleStyle.put( SelectItemButton.STYLE_FOREGROUND_UNSELECTED, colorValue );

		colorValue = (Color)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_FOREGROUND_SHADOW );
		if( colorValue == null )	{
			Logger.warn( MessageIDs.CVS3003W, new Object[]{SelectItemButton.STYLE_FOREGROUND_SHADOW, "black"} );
			colorValue = Color.black;
		}
		_titleStyle.put( SelectItemButton.STYLE_FOREGROUND_SHADOW, colorValue );

		Font	fontValue = (Font)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_FONT );
		if( fontValue == null )	{
			Map	attributes = new java.util.HashMap( 17 );
			attributes.put( TextAttribute.FAMILY, "SansSerif" );
			attributes.put( TextAttribute.SIZE, new Float(16f) );
			fontValue = FontManager.getInstance().getFont( attributes );
		}
		_titleStyle.put( SelectItemButton.STYLE_FONT, fontValue );
	}

	/**
	 * テキストキャンバスを取得します。
	 * @return	テキストキャンバス
	 */
	public TextCanvas getTextCanvas()
	{
		return _text;
	}

	/**
	 * ステージキャンバスを取得します。
	 * @return	ステージキャンバス
	 */
	public StageCanvas getStageCanvas()
	{
		return _stage;
	}

	/**
	 * ステージを取得します。
	 */
	public Stage getStage()
	{
		return _stage.getStage();
	}

	/**
	 * 現在のページを取得します。
	 */
	public Page getCurrentPage()
	{
		return _text.getPage();
	}

	/**
	 * 次の新しいページに移動します。
	 * @return	現在のページ(移動後)
	 */
	public Page advancesNewPage()
	{
		Page	page = _text.getPage();
		if( page != null )	{
			synchronized( page )	{
				putTextHistory( page );
				page.clearLines();
			}
		}
		else	{
			page = new Page();
			_text.setPage( page );
		}

		_currentPage = page;
		return page;
	}

	/**
	 * <code>page</code> をテキストの履歴に追加します。
	 * @param	page	履歴に追加するページ
	 */
	protected void putTextHistory( Page page )
	{
		if( page.getLineCount() == 0 )	{
			//	空白ページは履歴に入れないデス
			return;
		}

		Page	previous = null;
		if( _history.size() >= _maxHistoryCount )	{
			previous = (Page)_history.remove( 0 );
			page.clone( previous );
		}
		else	{
			previous = (Page)page.clone();
		}
		_history.add( previous );
	}

	/**
	 * 過去の文章を表示します。
	 * @param	index	戻るページ数。
	 * @return	次があれば true
	 */
	public boolean readAgain( int index )
	{
		if( _selecting )	{
			_select.setVisible( false );
		}

		Page	previous = (Page)_history.get( _history.size() - index );
		_text.setPage( previous );
		_text.updateCanvas();
		_text.updateText();
		return ((_history.size() - index) > 0);
	}

	/**
	 * 現在のページに戻ります。
	 */
	public void returnCurrent()
	{
		_text.setPage( _currentPage );
		_text.updateCanvas();
		_text.updateText();

		if( _selecting )	{
			hideTextCanvas();
			_select.setVisible( true );
		}
	}

	/**
	 * 履歴として保存されている過去のページ数を取得します。
	 * @return	履歴として保存されている過去のページ数
	 */
	public int getPageHistoryCount()
	{
		return _history.size();
	}

	/**
	 * 現在選択肢を表示中かどうかを取得します。
	 * @return	選択肢表示中の場合 <code>true</code>
	 */
	public boolean isShowingSelect()
	{
		return _selecting;
	}

	/**
	 * 選択肢を表示します。
	 * @param	selectItems	選択肢リスト
	 * @return	選択された選択肢の ID
	 */
	public String showSelect( List selectItems )
	{
		ResourceManager	resources = ResourceManager.getInstance();

		String	alignment = (String)resources.getResource( ResourceIDs.SELECT_ALIGN );
		if( alignment == null )	{
			Logger.warn( MessageIDs.CVS3001W, new Object[]{"center"} );
			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
		}
		else if( "center".equalsIgnoreCase(alignment) )	{
			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
		}
		else if( "left".equalsIgnoreCase(alignment) )	{
			_select.setAlignment( SelectCanvas.ALIGN_LEFT );
		}
		else if( "right".equalsIgnoreCase(alignment) )	{
			_select.setAlignment( SelectCanvas.ALIGN_RIGHT );
		}
		else	{
			Logger.warn( MessageIDs.CVS3001W, new Object[]{"center"} );
			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
		}

		String	valign = (String)resources.getResource( ResourceIDs.SELECT_VERTICAL_ALIGN );
		if( valign == null )	{
			Logger.warn( MessageIDs.CVS3006W, new Object[]{"middle"} );
			_select.setVerticalAlignment( SelectCanvas.VALIGN_MIDDLE );
		}
		else if( "top".equalsIgnoreCase(valign) )	{
			_select.setVerticalAlignment( SelectCanvas.VALIGN_TOP );
		}
		else if( "middle".equalsIgnoreCase(valign) )	{
			_select.setVerticalAlignment( SelectCanvas.VALIGN_MIDDLE );
		}
		else if( "bottom".equalsIgnoreCase(valign) )	{
			_select.setVerticalAlignment( SelectCanvas.VALIGN_BOTTOM );
		}
		else	{
			Logger.warn( MessageIDs.CVS3006W, new Object[]{"middle"} );
			_select.setVerticalAlignment( SelectCanvas.VALIGN_MIDDLE );
		}

		Integer	columns = (Integer)resources.getResource( ResourceIDs.SELECT_COLUMNS );
		if( columns == null )	{
			Logger.warn( MessageIDs.CVS3002W, new Object[]{"1"} );
			_select.setColumns( 1 );
		}
		else	{
			_select.setColumns( columns.intValue() );
		}

		Integer	span = (Integer)resources.getResource( ResourceIDs.SELECT_SPAN_COLUMN );
		if( span == null )	{
			Logger.warn( MessageIDs.CVS3004W, new Object[]{"5"} );
			_select.setColumnSpan( 5 );
		}
		else	{
			_select.setColumnSpan( span.intValue() );
		}

		span = (Integer)resources.getResource( ResourceIDs.SELECT_SPAN_ROW );
		if( span == null )	{
			Logger.warn( MessageIDs.CVS3005W, new Object[]{"5"} );
			_select.setRowSpan( 5 );
		}
		else	{
			_select.setRowSpan( span.intValue() );
		}

		span = (Integer)resources.getResource( ResourceIDs.SELECT_SPAN_BOUND );
		if( span == null )	{
			Logger.warn( MessageIDs.CVS3007W, new Object[]{"20"} );
			_select.setBoundSpan( 20 );
		}
		else	{
			_select.setBoundSpan( span.intValue() );
		}

		_select.setButtonStyle( _selectStyle );

		boolean	v = _text.isVisible();
		if( v )	{
//			_text.setVisible( false );
			hideTextCanvas();
		}

		Page	page = advancesNewPage();
		page.commit();

		_selecting = true;

		ActionControler	controler = PekoSystem.getInstance().getActionControler();
		if( controler.getPlayMode() == ActionControler.PM_SKIP )	{
			controler.setPlayModeToNormal();
		}

		_select.setVisible( true );
		String	id = _select.select( selectItems );
		_select.setVisible( false );

		if( v )	{
			_text.updateText();
		}

		_selecting = false;

		return id;
	}

	/**
	 * タイトル画面を描画します。
	 * @param	showTitle	オープニングを表示するかどうか
	 */
	public String showTitle( boolean showTitle )
	{
		ResourceManager	resources = ResourceManager.getInstance();

		String	alignment = (String)resources.getResource( ResourceIDs.TITLE_MENU_ALIGN );
		if( alignment == null )	{
			Logger.warn( MessageIDs.CVS3001W, new Object[]{"center"} );
			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
		}
		else if( "center".equalsIgnoreCase(alignment) )	{
			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
		}
		else if( "left".equalsIgnoreCase(alignment) )	{
			_select.setAlignment( SelectCanvas.ALIGN_LEFT );
		}
		else if( "right".equalsIgnoreCase(alignment) )	{
			_select.setAlignment( SelectCanvas.ALIGN_RIGHT );
		}
		else	{
			Logger.warn( MessageIDs.CVS3001W, new Object[]{"center"} );
			_select.setAlignment( SelectCanvas.ALIGN_CENTER );
		}

		String	valign = (String)resources.getResource( ResourceIDs.TITLE_MENU_VERTICAL_ALIGN );
		if( valign == null )	{
			Logger.warn( MessageIDs.CVS3006W, new Object[]{"bottom"} );
			_select.setVerticalAlignment( SelectCanvas.VALIGN_BOTTOM );
		}
		else if( "top".equalsIgnoreCase(valign) )	{
			_select.setVerticalAlignment( SelectCanvas.VALIGN_TOP );
		}
		else if( "middle".equalsIgnoreCase(valign) )	{
			_select.setVerticalAlignment( SelectCanvas.VALIGN_MIDDLE );
		}
		else if( "bottom".equalsIgnoreCase(valign) )	{
			_select.setVerticalAlignment( SelectCanvas.VALIGN_BOTTOM );
		}
		else	{
			Logger.warn( MessageIDs.CVS3006W, new Object[]{"bottom"} );
			_select.setVerticalAlignment( SelectCanvas.VALIGN_BOTTOM );
		}

		Integer	columns = (Integer)resources.getResource( ResourceIDs.TITLE_MENU_COLUMNS );
		if( columns == null )	{
			Logger.warn( MessageIDs.CVS3002W, new Object[]{"1"} );
			_select.setColumns( 1 );
		}
		else	{
			_select.setColumns( columns.intValue() );
		}

		String	startCaption = (String)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_CAPTION_START );
		if( startCaption == null )	{
			startCaption = "Start";
			Logger.warn( MessageIDs.CVS4001W, new Object[]{"start", startCaption} );
		}
		String	resumeCaption = (String)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_CAPTION_RESUME );
		if( resumeCaption == null )	{
			resumeCaption = "Load";
			Logger.warn( MessageIDs.CVS4001W, new Object[]{"resume", resumeCaption} );
		}
		String	exitCaption = (String)resources.getResource( ResourceIDs.TITLE_MENU_BUTTON_CAPTION_EXIT );
		if( exitCaption == null )	{
			exitCaption = "Exit";
			Logger.warn( MessageIDs.CVS4001W, new Object[]{"exit", exitCaption} );
		}

		_select.setButtonStyle( _titleStyle );

		Integer	span = (Integer)resources.getResource( ResourceIDs.TITLE_MENU_SPAN_COLUMN );
		if( span == null )	{
			Logger.warn( MessageIDs.CVS3004W, new Object[]{"5"} );
			_select.setColumnSpan( 5 );
		}
		else	{
			_select.setColumnSpan( span.intValue() );
		}

		span = (Integer)resources.getResource( ResourceIDs.TITLE_MENU_SPAN_ROW );
		if( span == null )	{
			Logger.warn( MessageIDs.CVS3005W, new Object[]{"5"} );
			_select.setRowSpan( 5 );
		}
		else	{
			_select.setRowSpan( span.intValue() );
		}

		span = (Integer)resources.getResource( ResourceIDs.TITLE_MENU_SPAN_BOUND );
		if( span == null )	{
			Logger.warn( MessageIDs.CVS3007W, new Object[]{"20"} );
			_select.setBoundSpan( 20 );
		}
		else	{
			_select.setBoundSpan( span.intValue() );
		}


		List	items = new java.util.ArrayList( 3 );
		SelectItem	item = new SelectItem();
		item.setID( "start" );
		item.setText( startCaption );
		items.add( item );
		item = new SelectItem();
		item.setID( "resume" );
		item.setText( resumeCaption );
		items.add( item );
		item = new SelectItem();
		item.setID( "exit" );
		item.setText( exitCaption );
		items.add( item );

		if( showTitle )	{
			String	imageName = (String)resources.getResource( ResourceIDs.TITLE_IMAGE );
			if( (imageName != null) && (imageName.length() > 0) )	{
				_stage.getStage().setBackgroundImage( imageName );
			}
			else	{
				_stage.getStage().setBackgroundColor( "white" );
			}
			_stage.updateCanvas( "mofing" );

			String	bgmName = (String)resources.getResource( ResourceIDs.OPENING_BGM, true );
			if( (bgmName != null) && (bgmName.length() > 0) )	{
				Logger.debug( "playBGM: " + bgmName );
				_stage.getStage().getAudioPlayer().playBGM( "opening", bgmName, true );
			}
		}

		hideTextCanvas();

		_selecting = true;
		_select.setVisible( true );
		String	id = _select.select( items );
		_select.setVisible( false );
		_selecting = false;

		return id;
	}


	/**
	 * テキストキャンバスを隠します。
	 */
	public void hideTextCanvas()
	{
		_text.setVisible( false );
		_stage.paintPageBackground( false );
	}

	/**
	 * テキストキャンバスを表示します。
	 */
	public void showTextCanvas()
	{
		_stage.paintPageBackground( true );
		_text.setVisible( true );
	}


	/**
	 * キャンバスを全てクリアし、初期状態に戻します。
	 */
	public synchronized void clearAll()
	{
		Logger.debug( "[canvas] clear All." );
		_select.setVisible( false );
		hideTextCanvas();
//		_text.setVisible( false );
		_select.cancel();
		_stage.getStage().getAudioPlayer().stopAll();
		advancesNewPage();
		_text.getPage().commit();
		_history.clear();
		Stage	stage = _stage.getStage();
		stage.exitAll();
		stage.setBackgroundColor( "black" );
		stage.hideSlide();
		_stage.updateCanvas( "mofing" );
		stage.commit();
	}


	/**
	 * <code>serializableForm</code> に格納された状態を復元します。
	 * @param	session	状態を格納したオブジェクト
	 */
	public void resume( Session session )
	{
		Stage	stage = _stage.getStage();
		stage.setBackgroundColor( "black" );
		stage.updateCanvas( "mofing" );
		_stage.setVisible( false );

		try	{
			SerializableForm	form = (SerializableForm)session.getSessionAttribute( "canvasManager" );
			_text.setPage( form.page );
			_stage.setStage( form.stage );
			form.stage.prepare();
			form.page.rollback();
		}
		catch( Throwable th )	{
			Logger.fatal( "[canvas] unsupported serializable form.", th );
		}

		_stage.setVisible( true );
		_stage.getStage().getAudioPlayer().prepare();
	}

	/**
	 * 状態保存用のオブジェクトを取得します。
	 * @return	状態を格納したオブジェクト
	 */
	public void saveState( Session session )
	{
		SerializableForm	serializable = new SerializableForm();
		serializable.page = _text.getPage();
		serializable.stage = _stage.getStage();
		session.setSessionAttribute( "canvasManager", serializable );
	}



	/**
	 * Canvas の状態を保持します。
	 * @author	$Author: ppoi $
	 * @version	$Revision: 1.1.2.2 $
	 */
	public static class SerializableForm	implements Serializable	{

		/**
		 * Stage
		 */
		public Stage	stage = null;

		/**
		 * Page
		 */
		public Page	page = null;
	}
}
