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	1行の最大幅
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 }