View Javadoc

    1   /*
    2    * "Peko" Visual Novel System
    3    *
    4    * All Rights Reserved.
    5    * Copyright (c) 1999-2003 Tsukuba Bunko.
    6    *
    7    * $Id: TextCoordinator.java,v 1.2 2005/07/11 14:27:50 ppoi Exp $
    8    */
    9   package tsukuba_bunko.peko.scenario.text;
    10
    11  import	java.awt.Dimension;
    12
    13  import	java.awt.font.LineBreakMeasurer;
    14  import	java.awt.font.TextAttribute;
    15  import	java.awt.font.TextLayout;
    16
    17  import	java.text.AttributedString;
    18
    19  import	tsukuba_bunko.peko.Logger;
    20
    21  import	tsukuba_bunko.peko.canvas.text.Line;
    22  import	tsukuba_bunko.peko.canvas.text.Page;
    23
    24  import	tsukuba_bunko.peko.resource.ResourceManager;
    25
    26  import	tsukuba_bunko.peko.scenario.Coordinator;
    27  import	tsukuba_bunko.peko.scenario.SceneContext;
    28
    29
    30  /***
    31   * TextCanvas への操作を取り持つコーディネータモジュールです。
    32   * @author	$Author: ppoi $
    33   * @version	$Revision: 1.2 $
    34   */
    35  public class TextCoordinator	extends Coordinator	{
    36
    37  	/***
    38  	 * Page の設定を行ったかどうか
    39  	 */
    40  	protected boolean	_pageConfigured = false;
    41
    42  	/***
    43  	 * 行間隔
    44  	 */
    45  	protected float	_lineSpan = 0f;
    46
    47  	/***
    48  	 * 最終行
    49  	 */
    50  	protected Line	_lastLine = null;
    51
    52
    53  	/***
    54  	 * Dimension cache
    55  	 */
    56  	protected Dimension	_sizeCache = new Dimension();
    57
    58
    59  	/***
    60  	 * <code>TextCoordinator</code> のインスタンスを生成します。
    61  	 */
    62  	public TextCoordinator()
    63  	{
    64  		super();
    65  	}
    66
    67
    68  	public void prepare( SceneContext context, Thread activeThread )
    69  	{
    70  		super.prepare( context, activeThread );
    71  		_pageConfigured = false;
    72  		_lastLine = null;
    73  	}
    74
    75
    76  	/***
    77  	 * TextCanvas への操作を開始します。
    78  	 */
    79  	public void begin()
    80  	{
    81  		if( isActiveThread() )	{
    82  			_lastLine = null;
    83  			getActionControler().setSaveEnabled( true );
    84  		}
    85  	}
    86
    87  	/***
    88  	 * TextCanvas への操作を終了し、キャンバスの状態を確定します。
    89  	 */
    90  	public void commit()
    91  	{
    92  		if( isActiveThread() )	{
    93  			getActionControler().setSaveEnabled( false );
    94  			getCurrentPage().commit();
    95  		}
    96  	}
    97
    98  	/***
    99  	 * 表示する文章を TextCanvsa に送信します。
    100 	 * @param	text	表示する文章
    101 	 */
    102 	public void pushText( String text )
    103 	{
    104 		if( !isActiveThread() )	{
    105 			return;
    106 		}
    107
    108 		Page	page = getCurrentPage();
    109 		if( !_pageConfigured )	{
    110 			PageConfigurator.configure( page, getSceneContext() );
    111 			_pageConfigured = true;
    112 			_lineSpan = getLineSpan();
    113 		}
    114
    115 		int	length = text.length();
    116 		if( length == 0 )	{
    117 			Logger.debug( "[scnario.text] empty string is pecified." );
    118 			return;
    119 		}
    120
    121 		if( _lastLine != null )	{
    122 			text = _lastLine.getText() + text;
    123 			length = text.length();
    124 		}
    125 		Logger.debug( text );
    126
    127 		AttributedString	astring = new AttributedString( text );
    128 		astring.addAttribute( TextAttribute.FONT, page.getDefaultFont() );
    129 		astring.addAttribute( TextAttribute.FOREGROUND, page.getForeground() );
    130
    131 		LineBreakMeasurer	lbm = new LineBreakMeasurer( astring.getIterator(), page.getFontRenderContext() );
    132 		float	maxWidth = page.getMaxLineWidth();
    133 		float	lineSpan = _lineSpan;
    134 		boolean	conflictWait = false;
    135 		TextLayout	layout = null;
    136 		Line	line = null;
    137
    138 		layout = lbm.nextLayout( maxWidth );
    139 		line = new Line();
    140 		line.setTextLayout( layout );
    141 		line.setText( text.substring(0, lbm.getPosition()) );
    142 		line.setForeground( page.getForeground() );
    143 		line.setShadowColor( page.getShadow() );
    144
    145 		if( _lastLine == null )	{
    146 			if( isActiveThread() )	{
    147 				line.setLineSpan( lineSpan );	//	ホントはここで margin-top を設定するデス。
    148 				if( !page.isAdaptive(line) )	{
    149 					page = advancesNewPage();
    150 				}
    151 				page.addLine( line );
    152 			}
    153 			else	{
    154 				return;
    155 			}
    156 		}
    157 		else	{
    158 			line.setLineSpan( lineSpan );
    159 			if( isActiveThread() )	{
    160 				page.setLine( (page.getLineCount() - 1), line );
    161 				if( _lastLine.getText().equals(line.getText()) )	{
    162 					conflictWait = true;
    163 				}
    164 			}
    165 			else	{
    166 				return;
    167 			}
    168 		}
    169 		_lastLine = line;
    170
    171 		int	lastLinePosition = 0;
    172 		while( (lastLinePosition = lbm.getPosition()) < length )	{
    173 			line = new Line();
    174 			line.setTextLayout( lbm.nextLayout(maxWidth) );
    175 			line.setLineSpan( lineSpan );
    176 			line.setText( text.substring(lastLinePosition, lbm.getPosition()) );
    177 			line.setForeground( page.getForeground() );
    178 			line.setShadowColor( page.getShadow() );
    179 			if( isActiveThread() )	{
    180 				if( !page.isAdaptive(line) )	{
    181 					if( conflictWait )	{
    182 						conflictWait = false;
    183 					}
    184 					else	{
    185 						page.updateContents();
    186 						stop();	//	ここー！
    187 					}
    188 					page = advancesNewPage();
    189 				}
    190 				if( page != null )	{
    191 					page.addLine( line );
    192 					conflictWait = false;
    193 				}
    194 				else	{
    195 					return;
    196 				}
    197 				_lastLine = line;
    198 			}
    199 			else	{
    200 				return;
    201 			}
    202 		}
    203 		if( isActiveThread() )	{
    204 			page.updateContents();
    205 		}
    206 	}
    207
    208 	/***
    209 	 * 現在表示中のページを取得します。
    210 	 * @return	現在表示中のページ
    211 	 */
    212 	public Page getCurrentPage()
    213 	{
    214 		return getCanvasManager().getCurrentPage();
    215 	}
    216
    217 	/***
    218 	 * 新しいページに切り替え、新しいページを取得します。
    219 	 * @return	新しいページ
    220 	 */
    221 	public Page advancesNewPage()
    222 	{
    223 		if( isActiveThread() )	{
    224 			return getCanvasManager().advancesNewPage();
    225 		}
    226 		else	{
    227 			return null;
    228 		}
    229 	}
    230
    231 	/***
    232 	 * 処理を一時停止します。
    233 	 */
    234 	protected void stop()
    235 	{
    236 		if( isActiveThread() )	{
    237 			getActionControler().stop();
    238 		}
    239 	}
    240
    241 	/***
    242 	 * 行間隔を取得します。
    243 	 * @return	行間隔
    244 	 */
    245 	protected float getLineSpan()
    246 	{
    247 		SceneContext	context = getSceneContext();
    248 		String	value = context.getProperty( PropertyIDs.CANVAS_TEXT_LINESPAN );
    249 		if( value != null )	{
    250 			try	{
    251 				return Float.parseFloat( value );
    252 			}
    253 			catch( Exception e )	{
    254 				Logger.warn( MessageIDs.SCN2002W, e );
    255 			}
    256 		}
    257
    258 		ResourceManager	resources = ResourceManager.getInstance();
    259 		Float	lineSpan = (Float)resources.getResource( ResourceIDs.CANVAS_TEXT_LINESPAN );
    260 		if( lineSpan != null )	{
    261 			return lineSpan.floatValue();
    262 		}
    263 		else	{
    264 			Logger.warn( MessageIDs.SCN2001W, new Object[]{"20.0"} );
    265 			return 20f;
    266 		}
    267 	}
    268 }