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: SelectItemButton.java,v 1.3 2005/07/24 20:55:57 ppoi Exp $
    18   */
    19  package tsukuba_bunko.peko.canvas.select;
    20
    21  import	java.awt.AlphaComposite;
    22  import	java.awt.Color;
    23  import	java.awt.Dimension;
    24  import	java.awt.Font;
    25  import	java.awt.Graphics;
    26  import	java.awt.Graphics2D;
    27  import	java.awt.RenderingHints;
    28
    29  import	java.awt.event.MouseEvent;
    30  import	java.awt.event.MouseListener;
    31
    32  import	java.awt.font.LineBreakMeasurer;
    33  import	java.awt.font.TextAttribute;
    34
    35  import	java.text.AttributedString;
    36
    37  import	java.util.List;
    38  import	java.util.Map;
    39
    40  import	javax.swing.BorderFactory;
    41  import	javax.swing.JComponent;
    42
    43  import	tsukuba_bunko.peko.Logger;
    44  import	tsukuba_bunko.peko.PekoSystem;
    45
    46  import	tsukuba_bunko.peko.canvas.text.Line;
    47
    48
    49  /***
    50   * 選択肢をユーザーに選択させるためのボタンです。
    51   * @author	$Author: ppoi $
    52   * @version	$Revision: 1.3 $
    53   */
    54  public class SelectItemButton	extends	JComponent	implements MouseListener	{
    55
    56  	/***
    57  	 * serial version UID
    58  	 */
    59  	private static final long	serialVersionUID	= -3568148242179176104L;
    60
    61  	/***
    62  	 * ボタンスタイル：幅
    63  	 */
    64  	public static final String	STYLE_WIDTH = "select.button.witdth";
    65
    66  	/***
    67  	 * ボタンスタイル：背景色
    68  	 */
    69  	public static final String	STYLE_BACKGROUND_COLOR = "select.button.background.color";
    70
    71  	/***
    72  	 * ボタンスタイル：背景透明度
    73  	 */
    74  	public static final String	STYLE_BACKGROUND_TRANSPARENCY = "select.button.background.transparency";
    75
    76  	/***
    77  	 * ボタンスタイル：前景色(選択時)
    78  	 */
    79  	public static final String	STYLE_FOREGROUND_SELECTED = "select.button.foreground.selected";
    80
    81  	/***
    82  	 * ボタンスタイル：前景色(非選択時)
    83  	 */
    84  	public static final String	STYLE_FOREGROUND_UNSELECTED = "select.button.foreground.unselected";
    85
    86  	/***
    87  	 * ボタンスタイル：影
    88  	 */
    89  	public static final String	STYLE_FOREGROUND_SHADOW = "select.button.foreground.shadow";
    90
    91  	/***
    92  	 * ボタンスタイル：フォント
    93  	 */
    94  	public static final String	STYLE_FONT = "select.button.font";
    95
    96
    97  	/***
    98  	 * owner
    99  	 */
    100 	private SelectCanvas	_owner = null;
    101
    102
    103 	/***
    104 	 * 選択肢
    105 	 */
    106 	private SelectItem	_item = null;
    107
    108 	/***
    109 	 * lines
    110 	 */
    111 	private List	_lines = null;
    112
    113 	/***
    114 	 * active foreground color
    115 	 */
    116 	private Color	_foregroundActive = null;
    117
    118 	/***
    119 	 * non-active foreground color
    120 	 */
    121 	private Color	_foregroundNonActive = null;
    122
    123 	/***
    124 	 * 影
    125 	 */
    126 	private Color	_shadow = null;
    127
    128 	/***
    129 	 * 背景色を塗りつぶす際に使用する AlphaComposite
    130 	 */
    131 	private AlphaComposite	_alphaComposite = AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.5f );
    132
    133 	/***
    134 	 * 選択状態フラグ
    135 	 */
    136 	private boolean	_selected = false;
    137
    138 	/***
    139 	 * size cache
    140 	 */
    141 	private Dimension	_size = new Dimension();
    142
    143
    144 	/***
    145 	 * <code>SelectItemButton</code> のインスタンスを作成します。
    146 	 */
    147 	public SelectItemButton( SelectCanvas owner )
    148 	{
    149 		super();
    150 		setBorder( BorderFactory.createLoweredBevelBorder() );
    151 		addMouseListener( this );
    152 		_owner = owner;
    153 	}
    154
    155
    156 	public void addNotify()
    157 	{
    158 		super.addNotify();
    159 		synchronized( this )	{
    160 			notify();
    161 		}
    162 	}
    163
    164 	/***
    165 	 * 選択肢を設定します。
    166 	 * @param	item	選択肢
    167 	 */
    168 	public void setSelectItem( SelectItem item )
    169 	{
    170 		_item = item;
    171 	}
    172
    173 	/***
    174 	 * 選択肢を取得します。
    175 	 * @return	選択肢
    176 	 */
    177 	public SelectItem getSelectItem()
    178 	{
    179 		return _item;
    180 	}
    181
    182 	//	エラー処理は、CanvasManager でされている前提です。
    183 	public void prepare( Map style )
    184 	{
    185 		Color	colorValue = (Color)style.get( SelectItemButton.STYLE_FOREGROUND_SELECTED );
    186 		if( colorValue != null )	{
    187 			_foregroundActive = colorValue;
    188 		}
    189 		else	{
    190 			_foregroundActive = Color.white;
    191 		}
    192
    193 		colorValue = (Color)style.get( SelectItemButton.STYLE_FOREGROUND_UNSELECTED );
    194 		if( colorValue != null )	{
    195 			_foregroundNonActive = colorValue;
    196 		}
    197 		else	{
    198 			_foregroundNonActive = Color.darkGray;
    199 		}
    200
    201 		colorValue = (Color)style.get( SelectItemButton.STYLE_BACKGROUND_COLOR );
    202 		if( colorValue != null )	{
    203 			setBackground( colorValue );
    204 		}
    205 		else	{
    206 			setBackground( Color.black );
    207 		}
    208
    209 		colorValue = (Color)style.get( SelectItemButton.STYLE_FOREGROUND_SHADOW );
    210 		if( colorValue != null )	{
    211 			_shadow = colorValue;
    212 		}
    213 		else	{
    214 			_shadow = Color.black;
    215 		}
    216
    217 		setForeground( _foregroundNonActive );
    218
    219 		Float	fv = (Float)style.get( SelectItemButton.STYLE_BACKGROUND_TRANSPARENCY );
    220 		if( fv != null )	{
    221 			if( fv.floatValue() != _alphaComposite.getAlpha() )	{
    222 				_alphaComposite = AlphaComposite.getInstance( AlphaComposite.SRC_OVER, fv.floatValue() );
    223 			}
    224 		}
    225 		else	{
    226 			if( _alphaComposite.getAlpha() != 0.5f )	{
    227 				_alphaComposite = AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.5f );
    228 			}
    229 		}
    230
    231 		float	width = 320f;
    232 		Integer	intValue = (Integer)style.get( SelectItemButton.STYLE_WIDTH );
    233 		if( intValue != null )	{
    234 			width = intValue.floatValue();
    235 		}
    236
    237 		Font	fontValue = (Font)style.get( SelectItemButton.STYLE_FONT );
    238 		if( fontValue != null )	{
    239 			setFont( fontValue );
    240 		}
    241
    242 		prepareLabel( width, 2 );
    243 	}
    244
    245 	/***
    246 	 * 選択肢を表示する準備を行います。
    247 	 * @param	width	１行の最大幅
    248 	 * @param	maxRows	最大行数
    249 	 */
    250 	public void prepareLabel( float width, int maxRows )
    251 	{
    252 		if( _item == null )	{
    253 			Logger.error( "[canvas.text] not specified corresponding SelectItem." );
    254 			return;
    255 		}
    256
    257 		Graphics2D	g2 = (Graphics2D)PekoSystem.getInstance().getMainWindow().getGraphics();
    258 		g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
    259
    260 		List	lines = new java.util.ArrayList();
    261 		float	lineHeight = 0f;
    262
    263 		String	text = _item.getText();
    264 		AttributedString	astring = new AttributedString( text );
    265 		astring.addAttribute( TextAttribute.FONT, getFont() );
    266 		LineBreakMeasurer	lbm = new LineBreakMeasurer( astring.getIterator(), g2.getFontRenderContext() );
    267 		int	length = text.length();
    268 		Line	line = null;
    269 		for( int i = 0; (i < maxRows) && (lbm.getPosition() < length); ++i )	{
    270 			line = new Line();
    271 			line.setTextLayout( lbm.nextLayout(width) );
    272 			line.setShadowColor( _shadow );
    273 			lines.add( line );
    274 			lineHeight += line.getAscent();
    275 			lineHeight += line.getDescent();
    276 		}
    277 		_lines = lines;
    278
    279 		Dimension	componentSize = new Dimension( (int)width, (int)lineHeight + 10 );
    280 		setPreferredSize( componentSize );
    281 		setSize( componentSize );
    282 	}
    283
    284 	/***
    285 	 * この選択肢ボタンの選択状態を設定します。
    286 	 * @param	selected	選択されている場合 <code>true</code>、選択されていない場合 <code>false</code>
    287 	 */
    288 	public void setSelected( boolean selected )
    289 	{
    290 		if( _selected == selected )	{
    291 			return;
    292 		}
    293
    294 		if( selected )	{
    295 			setForeground( _foregroundActive );
    296 			_owner.itemSelecting( this );
    297 		}
    298 		else	{
    299 			setForeground( _foregroundNonActive );
    300 			_owner.itemDeselected( this );
    301 		}
    302 		_selected = selected;
    303 		repaint();
    304 	}
    305
    306
    307 //
    308 //	JComponent の実装
    309 //
    310 	public void paintComponent( Graphics g )
    311 	{
    312 		Graphics2D      g2 = (Graphics2D)g.create();
    313 		g2.setComposite( _alphaComposite );
    314 		g2.setColor( getBackground() );
    315 		Dimension       size = getSize( _size );
    316 		g2.fillRect( 0, 0, size.width, size.height );
    317
    318 		List    lines = _lines;
    319 		if( lines != null )     {
    320 			g2 = (Graphics2D)g;
    321 			int	length = lines.size();
    322 			float	x = 5f;
    323 			float	y = 5f;
    324 			Line	line = null;
    325 			for( int i = 0; i < length; ++i )       {
    326 				line = (Line)lines.get( i );
    327 				line.setForeground( getForeground() );
    328 				y += line.getAscent();
    329 				line.draw( g2, x, y );
    330 				y += line.getDescent();
    331 			}
    332 		}
    333 	}
    334
    335 //
    336 //	MouseListener の実装
    337 //
    338 	public void mousePressed( MouseEvent ev )
    339 	{
    340 	}
    341
    342 	public void mouseReleased( MouseEvent ev )
    343 	{
    344 	}
    345
    346 	public void mouseEntered( MouseEvent ev )
    347 	{
    348 		setSelected( true );
    349 	}
    350
    351 	public void mouseExited( MouseEvent ev )
    352 	{
    353 		setSelected( false );
    354 	}
    355
    356 	public void mouseClicked( MouseEvent ev )
    357 	{
    358 		if( _selected && (ev.getModifiers() == MouseEvent.BUTTON1_MASK) )	{
    359 			_owner.itemSelected( this );
    360 		}
    361 	}
    362
    363 }