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: TextCanvas.java,v 1.3 2005/07/23 17:57:02 ppoi Exp $
    18   */
    19  package tsukuba_bunko.peko.canvas.text;
    20
    21  import	java.awt.AlphaComposite;
    22  import	java.awt.Dimension;
    23  import	java.awt.Graphics;
    24  import	java.awt.Graphics2D;
    25  import	java.awt.Insets;
    26  import	java.awt.Point;
    27  import	java.awt.RenderingHints;
    28
    29  import	java.awt.font.FontRenderContext;
    30
    31  import	java.util.List;
    32
    33  import	javax.swing.BorderFactory;
    34  import	javax.swing.JComponent;
    35
    36  import	javax.swing.border.Border;
    37
    38  import	tsukuba_bunko.peko.Logger;
    39
    40
    41  /***
    42   * テキストを表示するキャンバスです。
    43   * @author	$Author: ppoi $
    44   * @version	$Revision: 1.3 $
    45   */
    46  public class TextCanvas	extends JComponent	{
    47
    48  	/***
    49  	 * serial version UID
    50  	 */
    51  	private static final long	serialVersionUID	= 2600492357487531048L;
    52
    53
    54  	/***
    55  	 * Page
    56  	 */
    57  	private Page	_page = null;
    58
    59
    60  	/***
    61  	 * Lines
    62  	 */
    63  	private List	_lines = null;
    64
    65  	/***
    66  	 * alpha-composite
    67  	 */
    68  	private AlphaComposite	_alphaComposite = AlphaComposite.getInstance( AlphaComposite.DST_OVER, 0.5f );
    69
    70  	/***
    71  	 * page size
    72  	 */
    73  	private Dimension	_size = new Dimension();
    74
    75  	/***
    76  	 * location
    77  	 */
    78  	private Point	_location = new Point( 0, 0 );
    79
    80  	/***
    81  	 * padding
    82  	 */
    83  	private Insets	_padding = new Insets( 0, 0, 0, 0 );
    84
    85
    86  	/***
    87  	 * cached FontRenderContext
    88  	 */
    89  	private FontRenderContext	_frc = null;
    90
    91
    92  	/***
    93  	 * marker
    94  	 */
    95  	private Marker	_marker = null;
    96
    97
    98  	/***
    99  	 * <code>TextCanvas</code> のインスタンスを作成します。
    100 	 */
    101 	public TextCanvas()
    102 	{
    103 		super();
    104 		initialize();
    105 	}
    106
    107
    108 	/***
    109 	 * ページに文字を描画するのに使用する <code>FontRenderContext</code> を取得します。
    110 	 * @return	ページに文字を描画するのに使用する <code>FontRenderContext</code>
    111 	 */
    112 	public FontRenderContext getFontRenderContext()
    113 	{
    114 		if( _frc == null )	{
    115 			synchronized( this )	{
    116 				if( _frc == null )	{
    117 					try	{
    118 						Logger.debug( "[canvas.text] waiting for create cached FontRenderContext." );
    119 						wait();
    120 						Logger.debug( "[canvas.text] creating cached FontRenderContext done." );
    121 					}
    122 					catch( InterruptedException ie )	{
    123 						Logger.error( "[canvas.text] interrupted." );
    124 					}
    125 				}
    126 			}
    127 		}
    128 		return _frc;
    129 	}
    130
    131 	/***
    132 	 * 背景色を描画する際に使用する AlphaComposite を取得します。
    133 	 * @return	背景色を描画する際に使用する AlphaComposite インスタンス
    134 	 */
    135 	public AlphaComposite getAlphaComposite()
    136 	{
    137 		return _alphaComposite;
    138 	}
    139
    140 	/***
    141 	 * キャンバスを最新の状態に更新します。
    142 	 */
    143 	public void updateCanvas()
    144 	{
    145 		if( !isEnabled() )	{
    146 			return;
    147 		}
    148
    149 		Logger.debug( "[canvas.text] update TextCanvas view" );
    150 		_lines = null;
    151 		_page.getSize( _size );
    152 		_page.getLocation( _location );
    153 		_page.getPadding( _padding );
    154 		setForeground( _page.getForeground() );
    155 		setBackground( _page.getBackground() );
    156 		float	trans = _page.getTransparency();
    157 		if( (_alphaComposite == null) || (_alphaComposite.getAlpha() != trans) )	{
    158 			_alphaComposite = AlphaComposite.getInstance( AlphaComposite.SRC_OVER, trans );
    159 		}
    160 		_marker.setText( "▼", _page );
    161 	}
    162
    163 	/***
    164 	 * キャンバスに描画するテキストを最新の状態に更新します。
    165 	 */
    166 	public void updateText()
    167 	{
    168 		if( !isEnabled() )	{
    169 			return;
    170 		}
    171
    172 		Logger.debug( "[canvas.text] update texts." );
    173 		_marker.setVisible( false );
    174
    175 		List	lines = _page.getLines();
    176 		int size = lines.size();
    177 		for( int i = 0; i < size; ++i )	{
    178 			((Line)lines.get(i)).prepare( _page );
    179 		}
    180 		_lines = lines;
    181
    182 //		setVisible( true );
    183 		tsukuba_bunko.peko.PekoSystem.getInstance().getCanvasManager().showTextCanvas();
    184 		repaint();
    185
    186 		try	{
    187 			synchronized( this )	{
    188 				wait( 100 );
    189 			}
    190 		}
    191 		catch( Exception e )	{
    192 		}
    193 		_marker.setVisible( true );
    194 	}
    195
    196
    197 	/***
    198 	 * このキャンバスで描画するページを設定します。
    199 	 * @param	page	このキャンバスで描画するページ
    200 	 */
    201 	public void setPage( Page page )
    202 	{
    203 		_page = page;
    204 		_page.setTextCanvas( this );
    205 	}
    206
    207 	/***
    208 	 * 現在このキャンバスで描画中のページを取得します。
    209 	 * @return	現在このキャンバスで描画中のページ
    210 	 */
    211 	public Page getPage()
    212 	{
    213 		return _page;
    214 	}
    215
    216 	public void paintPageBackground( Graphics g )
    217 	{
    218 		Dimension	size = _size;
    219 		Point	location = _location;
    220
    221 		Graphics2D	g2 = (Graphics2D)g.create( location.x, location.y, size.width, size.height );
    222 		g2.setComposite( _alphaComposite );
    223 		g2.setColor( getBackground() );
    224 		g2.fillRect( 0, 0, size.width, size.height );
    225 		g2.dispose();
    226 	}
    227
    228 	/***
    229 	 * TextCanvas を初期化します。
    230 	 */
    231 	private void initialize()
    232 	{
    233 		setLayout( null );
    234 		setDoubleBuffered( false );
    235 		setBorder( BorderFactory.createEtchedBorder() );
    236
    237 		_marker = new Marker();
    238 		add( _marker );
    239 		_marker.setLocation( 0, 0 );
    240 		_marker.setVisible( false );
    241 	}
    242
    243
    244 //
    245 //	JComponent の実装
    246 //
    247 	public void setVisible( boolean visibility )
    248 	{
    249 		Logger.debug( "[canvas.text] set visibility :" + visibility );
    250 		if( visibility )	{
    251 			_marker.start();
    252 		}
    253 		super.setVisible( visibility );
    254 	}
    255
    256 	public void addNotify()
    257 	{
    258 		super.addNotify();
    259 		Logger.debug( "[canvas.text] added notify to TextCavas" );
    260 		if( _frc == null )	{
    261 			Logger.debug( "[canvas.text] try create new font render context." );
    262 			synchronized( this )	{
    263 				if( _frc == null )	{
    264 					Graphics2D	g2 = (Graphics2D)getGraphics();
    265 					g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
    266 					_frc = g2.getFontRenderContext();
    267 					Logger.debug( "[canvas] notify all thread waiting at TextCanvas" );
    268 					notifyAll();
    269 				}
    270 			}
    271 		}
    272 	}
    273
    274 	public void paint( Graphics g )
    275 	{
    276 		List	lines = _lines;
    277 		if( (lines == null) || lines.isEmpty() )	{
    278 			return;
    279 		}
    280 		else	{
    281 			super.paint( g );
    282 		}
    283 	}
    284
    285 	public void paintBorder( Graphics g )
    286 	{
    287 		Border	border = getBorder();
    288 		if( border != null )	{
    289 			border.paintBorder( this, g, _location.x, _location.y, _size.width, _size.height );
    290 		}
    291 	}
    292
    293 	public void paintComponent( Graphics g )
    294 	{
    295 		List	lines = _lines;
    296
    297 		Point	location = _location;
    298 		Insets	padding = _padding;
    299
    300 //		paintPageBackground( g );
    301
    302 		Graphics2D	g2 = (Graphics2D)g;
    303 		float	x = (float)(location.x + padding.left);
    304 		float	y = (float)(location.y + padding.top);
    305 		float	tail = 0f;
    306 		int	length = lines.size();
    307 		Line	line = null;
    308 		for( int i = 0; i < length; ++i )	{
    309 			line = (Line)lines.get( i );
    310 			y += line.getAscent();
    311 			line.draw( g2, x, y );
    312 			y += line.getDescent();
    313 			tail = line.getAdavance();
    314 		}
    315 		_marker.setPosition( (int)(tail + 5f + x), (int)y );
    316 	}
    317 }