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: ActionControler.java,v 1.6 2005/07/23 18:45:12 ppoi Exp $
18   */
19  package tsukuba_bunko.peko;
20  
21  import	java.awt.event.ActionListener;
22  import	java.awt.event.MouseEvent;
23  import	java.awt.event.MouseListener;
24  import	java.awt.event.KeyEvent;
25  import	java.awt.event.KeyListener;
26  
27  import	java.text.MessageFormat;
28  
29  import	java.util.Timer;
30  import	java.util.TimerTask;
31  
32  import	javax.swing.ButtonGroup;
33  import	javax.swing.ImageIcon;
34  import	javax.swing.JButton;
35  import	javax.swing.JCheckBoxMenuItem;
36  import	javax.swing.JDialog;
37  import	javax.swing.JFrame;
38  import	javax.swing.JMenu;
39  import	javax.swing.JMenuBar;
40  import	javax.swing.JMenuItem;
41  import	javax.swing.JOptionPane;
42  import	javax.swing.JRadioButtonMenuItem;
43  import	javax.swing.KeyStroke;
44  
45  import	tsukuba_bunko.util.GenericListener;
46  
47  import	tsukuba_bunko.peko.canvas.CanvasManager;
48  
49  import	tsukuba_bunko.peko.resource.ResourceManager;
50  
51  
52  /***
53   * プレイヤーの操作を受け付けるコントローラです。
54   * @author	$Author: ppoi $
55   * @version	$Revision: 1.6 $
56   */
57  public class ActionControler	implements KeyListener, MouseListener	{
58  
59  	/***
60  	 * プレイヤーが操作するまで停止するストップモード(デフォルト)
61  	 */
62  	public static final long	SM_DEFAULT = -1;
63  
64  	/***
65  	 * ノンストップモード
66  	 */
67  	public static final long	SM_NONSTOP = 0;
68  
69  
70  	/***
71  	 * 早送りプレイ(次の選択肢までスキップ)モード
72  	 */
73  	public static final int	PM_SKIP = 1;
74  
75  	/***
76  	 * 通常プレイモード
77  	 */
78  	public static final int PM_NORMAL = 0;
79  
80  	/***
81  	 * 自動送りプレイモード
82  	 */
83  	public static final int	PM_AUTOMATIC = 2;
84  
85  
86  	/***
87  	 */
88  	private Object	_lock = this;
89  
90  	/***
91  	 * 有効かどうか
92  	 */
93  	private boolean	_activity = false;
94  
95  	/***
96  	 * プレイモード
97  	 */
98  	private int	_playMode = -1;
99  
100 	/***
101 	 * プレイモード変更ボタン(メニュー)リスト
102 	 */
103 	private JMenuItem[]	_buttons = new JMenuItem[3];
104 
105 	/***
106 	 * エフェクトを使用しないメニュー
107 	 */
108 	private JMenuItem	_usingEffectMenu = null;
109 
110 	/***
111 	 * セーブメニュー
112 	 */
113 	private JMenuItem	_saveMenu = null;
114 
115 	/***
116 	 * ロードメニュー
117 	 */
118 	private JMenuItem	_loadMenu = null;
119 
120 	/***
121 	 * タイトルに戻るメニュー
122 	 */
123 	private JMenuItem	_returnTileMenu = null;
124 
125 	/***
126 	 * 過去の文章メニュー
127 	 */
128 	private JMenuItem	_readAgainMenu = null;
129 
130 	/***
131 	 * タイマー
132 	 */
133 	private Timer	_timer = new Timer( true );
134 
135 	/***
136 	 * 最新のタスク
137 	 */
138 	private TimerTask	_lastTask = null;
139 
140 
141 	/***
142 	 * 読み返しコントローラ
143 	 */
144 	private TextHistoryControler	_readAgainControler = null;
145 
146 	/***
147 	 * 最後に押されたキーのキーコード
148 	 */
149 	private int	_lastKeyCode = -1;
150 
151 	/***
152 	 * active 待ちかどうか
153 	 */
154 	private boolean	_waitingActivate = false;
155 
156 	/***
157 	 * テキストを隠しているかどうか
158 	 */
159 	private boolean	_hiddenText = false;
160 
161 
162 	/***
163 	 * <code>ActionControler</code> のインスタンスを作成します。
164 	 */
165 	public ActionControler()
166 	{
167 		super();
168 		prepareMenuBar();
169 		setPlayModeToNormal();
170 	}
171 
172 	/***
173 	 * ActionContorler を有効にするかどうかを設定します。
174 	 * @param	activity	有効にする場合 <code>false</code>、それ以外 <code>false</code>。
175 	 */
176 	public void setActive( boolean activity )
177 	{
178 		_activity = activity;
179 		if( !activity )	{
180 			_lastKeyCode = -1;
181 		}
182 		else if( _playMode != ActionControler.PM_NORMAL )	{
183 			if( _waitingActivate )	{
184 				synchronized( _lock )	{
185 					if( _waitingActivate )	{
186 						_lock.notify();
187 					}
188 				}
189 			}
190 		}
191 	}
192 
193 	/***
194 	 * ActionControler が有効かどうかを判定します。
195 	 * @return	有効な場合 <code>true</code>、それ以外 <code>false</code>。
196 	 */
197 	public boolean isActive()
198 	{
199 		return _activity && !PekoSystem.getInstance().getCanvasManager().isShowingSelect();
200 	}
201 
202 	/***
203 	 * セーブ機能の有効/無効を設定します。
204 	 * @param	enabled	有効にする場合 <code>true</code>、それ以外の場合 <code>false</code>
205 	 */
206 	public synchronized void setSaveEnabled( boolean enabled )
207 	{
208 		_saveMenu.setEnabled( enabled );
209 	}
210 
211 	/***
212 	 * 現在のプレイモードを取得します。
213 	 */
214 	public int getPlayMode()
215 	{
216 		return _playMode;
217 	}
218 
219 	/***
220 	 * プレイモードを設定します。
221 	 * @param	playMode	プレイモード。<code>PM_FORWARD</code>、<code>PM_NORMAL</code>、<code>PM_AUTOMATIC</code> から選択。
222 	 */
223 	protected void setPlayMode( int playMode )
224 	{
225 		_playMode = playMode;
226 		_buttons[playMode].setSelected( true );
227 		if( playMode == ActionControler.PM_SKIP )	{
228 			_readAgainMenu.setEnabled( false );
229 		}
230 		else if( !_readAgainMenu.isEnabled() )	{
231 			_readAgainMenu.setEnabled( true );
232 		}
233 		PekoSystem.getInstance().getCanvasManager().getStageCanvas().setUsingEffect( !_usingEffectMenu.isSelected() && (playMode != ActionControler.PM_SKIP) );
234 		if( (_playMode != ActionControler.PM_NORMAL) && !PekoSystem.getInstance().getCanvasManager().isShowingSelect() )	{
235 			start();
236 		}
237 	}
238 
239 	/***
240 	 * プレイモードを「早送り」に設定します。
241 	 */
242 	public void setPlayModeToSKip()
243 	{
244 		setPlayMode( ActionControler.PM_SKIP );
245 	}
246 
247 	/***
248 	 * プレイモードを「通常」に設定します。
249 	 */
250 	public void setPlayModeToNormal()
251 	{
252 		setPlayMode( ActionControler.PM_NORMAL );
253 	}
254 
255 	/***
256 	 * プレイモードを「自動」に設定します。
257 	 */
258 	public void setPlayModeToAutomatic()
259 	{
260 		setPlayMode( ActionControler.PM_AUTOMATIC );
261 	}
262 
263 	/***
264 	 * 画像切り替えエフェクトを使用するかどうかを切り替えます。
265 	 */
266 	public void changeUsingEffect()
267 	{
268 		PekoSystem.getInstance().getCanvasManager().getStageCanvas().setUsingEffect( !_usingEffectMenu.isSelected() && (_playMode != ActionControler.PM_SKIP) );
269 	}
270 
271 	/***
272 	 * 読み返しコントローラを表示します。
273 	 */
274 	public void showReadAgain()
275 	{
276 		setActive( false );
277 		_saveMenu.setEnabled( false );
278 		_loadMenu.setEnabled( false );
279 		_returnTileMenu.setEnabled( false );
280 		_readAgainMenu.setEnabled( false );
281 		if( _readAgainControler == null )	{
282 			_readAgainControler = new TextHistoryControler();
283 			_readAgainControler.setLocationRelativeTo( PekoSystem.getInstance().getMainWindow() );
284 		}
285 		_readAgainControler.setVisible( true );
286 		setActive( true );
287 		_saveMenu.setEnabled( true );
288 		_loadMenu.setEnabled( true );
289 		_returnTileMenu.setEnabled( true );
290 		_readAgainMenu.setEnabled( true );
291 	}
292 
293 	/***
294 	 * ロードダイアログを表示します。
295 	 */
296 	public void showLoadDialog()
297 	{
298 		setActive( false );
299 		_saveMenu.setEnabled( false );
300 		_loadMenu.setEnabled( false );
301 		_returnTileMenu.setEnabled( false );
302 		_readAgainMenu.setEnabled( false );
303 		PekoSystem	system = PekoSystem.getInstance();
304 		if( !system.load() )	{
305 			setActive( true );
306 		}
307 		_saveMenu.setEnabled( true );
308 		_loadMenu.setEnabled( true );
309 		_returnTileMenu.setEnabled( true );
310 		_readAgainMenu.setEnabled( true );
311 	}
312 
313 	/***
314 	 * セーブダイアログを表示します。
315 	 */
316 	public synchronized void showSaveDialog()
317 	{
318 		PekoSystem	system = PekoSystem.getInstance();
319 		setActive( false );
320 		_saveMenu.setEnabled( false );
321 		_loadMenu.setEnabled( false );
322 		_returnTileMenu.setEnabled( false );
323 		_readAgainMenu.setEnabled( false );
324 		system.save();
325 		_saveMenu.setEnabled( true );
326 		_loadMenu.setEnabled( true );
327 		_returnTileMenu.setEnabled( true );
328 		_readAgainMenu.setEnabled( true );
329 		setActive( true );
330 	}
331 
332 	/***
333 	 * タイトル画面に戻ります。
334 	 */
335 	public void returnTitle()
336 	{
337 		returnTitle( false );
338 	}
339 
340 	/***
341 	 * タイトル画面に戻ります。
342 	 */
343 	public void returnTitle( boolean silence )
344 	{
345 		setActive( false );
346 		setPlayMode( ActionControler.PM_NORMAL );
347 		_saveMenu.setEnabled( false );
348 		_loadMenu.setEnabled( false );
349 		_returnTileMenu.setEnabled( false );
350 		_readAgainMenu.setEnabled( false );
351 		if( silence )	{
352 			PekoSystem.getInstance().showTitle();
353 		}
354 		else	{
355 			ResourceManager	resources = ResourceManager.getInstance();
356 			String	message = (String)resources.getResource( "peko.dialog.return-title.message" );
357 			if( message == null )	{
358 				message = "Are you return title ?";
359 			}
360 
361 			String	title = (String)resources.getResource( "peko.dialog.return-title.title" );
362 			if( title == null )	{
363 				title = "Confirm";
364 			}
365 
366 			if( JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog(PekoSystem.getInstance().getMainWindow(), message, title, JOptionPane.OK_CANCEL_OPTION) )	{
367 				PekoSystem.getInstance().showTitle();
368 			}
369 			else	{
370 				setActive( true );
371 			}
372 		}
373 		_saveMenu.setEnabled( true );
374 		_loadMenu.setEnabled( true );
375 		_returnTileMenu.setEnabled( true );
376 		_readAgainMenu.setEnabled( true );
377 	}
378 
379 
380 	/***
381 	 * {@link #stop()} により停止されたスレッドを再開します。
382 	 */
383 	public void start()
384 	{
385 		synchronized( _lock )	{
386 			if( _lastTask != null )	{
387 				_lastTask.cancel();
388 			}
389 			_lastTask = null;
390 			_lock.notify();
391 			Logger.debug( "[system.controler] notify to finish wait." );
392 		}
393 	}
394 
395 	/***
396 	 * プレイヤーがアクションを起こすまで現在のスレッドを停止します。
397 	 */
398 	public void stop()
399 	{
400 		stop( ActionControler.SM_DEFAULT );
401 	}
402 
403 	/***
404 	 * 現在のスレッドを停止します。
405 	 * @param	wait	待ち時間。プレイヤーが操作するまでストップする場合は <code>SM_DEFAULT</code> を、無停止の場合は <code>SM_NONSTOP</code> を指定する。
406 	 */
407 	public void stop( long wait )
408 	{
409 		Logger.debug( "[system.controler] stop :" + wait );
410 		if( (wait == 0) || (_playMode == ActionControler.PM_SKIP) )	{
411 			//NOOP
412 		}
413 		else if( wait < 0 )	{
414 			synchronized( _lock )	{
415 				try	{
416 					if( (_playMode == ActionControler.PM_AUTOMATIC) && !PekoSystem.getInstance().getCanvasManager().isShowingSelect() )	{
417 						TimerTask	task = new TimerTask()	{
418 							public void run()	{
419 								synchronized( _lock )	{
420 									_lock.notify();
421 								}
422 							}
423 						};
424 						_timer.schedule( task, 1000L );
425 						_lastTask = task;
426 					}
427 					_lock.wait();
428 				}
429 				catch( InterruptedException ie )	{
430 					Logger.debug( "[system.action] interrupted." );
431 				}
432 			}
433 		}
434 		else	{
435 			synchronized( _lock )	{
436 				try	{
437 					TimerTask	task = new TimerTask()	{
438 						public void run()	{
439 							synchronized( _lock )	{
440 								_lock.notify();
441 							}
442 						}
443 					};
444 					_timer.schedule( task, wait );
445 					_lastTask = task;
446 					_lock.wait();
447 				}
448 				catch( InterruptedException ie )	{
449 					Logger.debug( "[system.action] interrupted." );
450 				}
451 			}
452 		}
453 
454 		if( !isActive() && (_lastTask != null) )	{
455 			synchronized( _lock )	{
456 				if( !_activity && (_lastTask != null) )	{
457 					_waitingActivate = true;
458 					try	{
459 						_lock.wait();
460 						_lock.wait( 500 );
461 					}
462 					catch( InterruptedException ie )	{
463 					}
464 					_waitingActivate = false;
465 				}
466 			}
467 		}
468 
469 		_lastTask = null;
470 		Logger.debug( "[system.controler] finish wait." );
471 	}
472 
473 
474 	/***
475 	 * メニューバーを準備します。
476 	 */
477 	private void prepareMenuBar()
478 	{
479 		PekoSystem	system = PekoSystem.getInstance();
480 		ResourceManager	resources = ResourceManager.getInstance();
481 
482 		JMenuBar	menubar = new JMenuBar();
483 		JMenu	menu = null;
484 		JMenuItem	item = null;
485 
486 		menu = new JMenu( (String)resources.getResource("peko.menu.system.menu-caption") );
487 		menu.setMnemonic( 'S' );
488 		menubar.add( menu );
489 
490 		item = new JMenuItem( (String)resources.getResource("peko.menu.system.save") );
491 		item.setEnabled( false );
492 		item.setMnemonic( 'S' );
493 		item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK) );
494 		GenericListener.connect( item, this, ActionListener.class, "actionPerformed", "showSaveDialog", true );
495 		menu.add( item );
496 		_saveMenu = item;
497 
498 		item = new JMenuItem( (String)resources.getResource("peko.menu.system.load") );
499 		item.setEnabled( false );
500 		item.setMnemonic( 'O' );
501 		item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK) );
502 		GenericListener.connect( item, this, ActionListener.class, "actionPerformed", "showLoadDialog", true );
503 		menu.add( item );
504 		_loadMenu = item;
505 
506 		menu.addSeparator();
507 
508 		item = new JMenuItem( (String)resources.getResource("peko.menu.system.return-title") );
509 		item.setEnabled( false );
510 		item.setMnemonic( 'T' );
511 		item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_MASK) );
512 		GenericListener.connect( item, this, ActionListener.class, "actionPerformed", "returnTitle", true );
513 		menu.add( item );
514 		_returnTileMenu = item;
515 
516 		item = new JMenuItem( (String)resources.getResource("peko.menu.system.read-again") );
517 		item.setEnabled( false );
518 		item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_R, 0) );
519 		item.setMnemonic( 'R' );
520 		GenericListener.connect( item, this, ActionListener.class, "actionPerformed", "showReadAgain" );
521 		menu.add( item );
522 		_readAgainMenu = item;
523 
524 		menu.addSeparator();
525 
526 		item = new JMenuItem( (String)resources.getResource("peko.menu.system.exit") );
527 		item.setMnemonic( 'X' );
528 		item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_MASK) );
529 		GenericListener.connect( item, system, ActionListener.class, "actionPerformed", "exit" );
530 		menu.add( item );
531 
532 
533 		menu = new JMenu( (String)resources.getResource("peko.menu.config.menu-caption") );
534 		menu.setMnemonic( 'C' );
535 		menubar.add( menu );
536 
537 		JMenu	submenu = new JMenu( (String)resources.getResource("peko.menu.config.playmode.menu-caption") );
538 		submenu.setMnemonic( 'P' );
539 		menu.add( submenu );
540 
541 		ButtonGroup	group = new ButtonGroup();
542 		item = new JRadioButtonMenuItem( (String)resources.getResource("peko.menu.config.playmode.normal") );
543 		item.setMnemonic( 'N' );
544 //		item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK) );
545 		GenericListener.connect( item, this, ActionListener.class, "actionPerformed", "setPlayModeToNormal" );
546 		group.add( item );
547 		submenu.add( item );
548 		_buttons[ ActionControler.PM_NORMAL ] = item;
549 
550 		item = new JRadioButtonMenuItem( (String)resources.getResource("peko.menu.config.playmode.automatic") );
551 		item.setMnemonic( 'A' );
552 //		item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK) );
553 		GenericListener.connect( item, this, ActionListener.class, "actionPerformed", "setPlayModeToAutomatic" );
554 		group.add( item );
555 		submenu.add( item );
556 		_buttons[ ActionControler.PM_AUTOMATIC ] = item;
557 
558 		item = new JRadioButtonMenuItem( (String)resources.getResource("peko.menu.config.playmode.skip") );
559 		item.setMnemonic( 'S' );
560 		item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_S, 0) );
561 		GenericListener.connect( item, this, ActionListener.class, "actionPerformed", "setPlayModeToSKip" );
562 		group.add( item );
563 		submenu.add( item );
564 		_buttons[ ActionControler.PM_SKIP ] = item;
565 
566 		menu.addSeparator();
567 
568 		item = new JCheckBoxMenuItem( (String)resources.getResource("peko.menu.config.use-effect") );
569 		item.setSelected( false );
570 		item.setMnemonic( 'E' );
571 		GenericListener.connect( item, this, ActionListener.class, "actionPerformed", "changeUsingEffect" );
572 		menu.add( item );
573 		_usingEffectMenu = item;
574 
575 
576 		menu = new JMenu( (String)resources.getResource("peko.menu.help.menu-caption") );
577 		menu.setMnemonic( 'H' );
578 		menubar.add( menu );
579 
580 		item = new JMenuItem( (String)resources.getResource("peko.menu.help.help-contents") );
581 		item.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0) );
582 		item.setMnemonic( 'H' );
583 		item.setEnabled( false );
584 //		GenericListener.connect( item, system, ActionListener.class, "actionPerformed", "showGameVersionInfo" );
585 		menu.add( item );
586 
587 		item = new JMenuItem( (String)resources.getResource("peko.menu.help.version") );
588 		item.setMnemonic( 'A' );
589 		GenericListener.connect( item, system, ActionListener.class, "actionPerformed", "showGameVersionInfo" );
590 		menu.add( item );
591 
592 		menu.addSeparator();
593 
594 		item = new JMenuItem( (String)resources.getResource("peko.menu.help.about-pvns") );
595 		item.setMnemonic( 'P' );
596 		GenericListener.connect( item, system, ActionListener.class, "actionPerformed", "showSystemVersionInfo" );
597 		menu.add( item );
598 
599 
600 		JFrame	mainWindow = system.getMainWindow();
601 		mainWindow.setJMenuBar( menubar );
602 		mainWindow.pack();
603 		mainWindow.setResizable( false );
604 	}
605 
606 
607 //
608 //	MouseListener の実装
609 //
610 	public void mousePressed( MouseEvent ev )
611 	{
612 	}
613 
614 	public void mouseReleased( MouseEvent ev )
615 	{
616 	}
617 
618 	public void mouseEntered( MouseEvent ev )
619 	{
620 	}
621 
622 	public void mouseExited( MouseEvent ev )
623 	{
624 	}
625 
626 	public void mouseClicked( MouseEvent ev )
627 	{
628 		int	code = ev.getModifiers();
629 		if( isActive() && (code == MouseEvent.BUTTON1_MASK) )	{
630 			start();
631 		}
632 		else if( (_playMode == ActionControler.PM_SKIP) && (code == MouseEvent.BUTTON3_MASK) )	{
633 			setPlayModeToNormal();
634 			return;
635 		}
636 		else if( _hiddenText )	{
637 			CanvasManager	canvasManager = PekoSystem.getInstance().getCanvasManager();
638 			canvasManager.hideTextCanvas();
639 			setActive( true );
640 		}
641 	}
642 
643 
644 //
645 //	KeyListener の実装
646 //
647 	public void keyPressed( KeyEvent ev )
648 	{
649 		if( isActive() )	{
650 			int	code = ev.getKeyCode();
651 			if( _lastKeyCode == -1 )	{
652 				_lastKeyCode = code;
653 			}
654 			else if( _lastKeyCode != code )	{
655 				_lastKeyCode = -1;
656 			}
657 		}
658 	}
659 
660 	public void keyReleased( KeyEvent ev )
661 	{
662 		int	code = ev.getKeyCode();
663 		if( code != _lastKeyCode )	{
664 			_lastKeyCode = -1;
665 			return;
666 		}
667 
668 		if( _hiddenText )	{
669 			CanvasManager	canvasManager = PekoSystem.getInstance().getCanvasManager();
670 			canvasManager.showTextCanvas();
671 			_saveMenu.setEnabled( true );
672 			_loadMenu.setEnabled( true );
673 			_returnTileMenu.setEnabled( true );
674 			_hiddenText = false;
675 		}
676 		else if( isActive() && (code == KeyEvent.VK_ENTER) )	{
677 			start();
678 		}
679 		else if( (_playMode != ActionControler.PM_NORMAL) && (code == KeyEvent.VK_ESCAPE) )	{
680 			setPlayModeToNormal();
681 		}
682 		else if( !_hiddenText && (code == KeyEvent.VK_SPACE) )	{
683 			CanvasManager	canvasManager = PekoSystem.getInstance().getCanvasManager();
684 			_saveMenu.setEnabled( false );
685 			_loadMenu.setEnabled( false );
686 			_returnTileMenu.setEnabled( false );
687 			canvasManager.hideTextCanvas();
688 			_hiddenText = true;
689 		}
690 		_lastKeyCode = -1;
691 	}
692 
693 	public void keyTyped( KeyEvent ev )
694 	{
695 	}
696 }
697 
698 
699 
700 
701 /***
702  * テキストの履歴をブラウジングするコントローラです。
703  */
704 class TextHistoryControler	extends JDialog	{
705 
706 	/***
707 	 * serial version UID
708 	 */
709 	private static final long	serialVersionUID	= -5321584449609116120L;
710 
711 	/***
712 	 * 現在のインデックス
713 	 */
714 	private int	_index = 0;
715 
716 	/***
717 	 * キャンバスマネージャ
718 	 */
719 	private CanvasManager	_canvasManager = null;
720 
721 	/***
722 	 * 「前」ボタン
723 	 */
724 	private JButton	_previous = null;
725 
726 	/***
727 	 * 「次」ボタン
728 	 */
729 	private JButton	_next = null;
730 
731 
732 	/***
733 	 * <code>TextHistoryControler</code> のインスタンスを作成します。
734 	 */
735 	public TextHistoryControler()
736 	{
737 		super( PekoSystem.getInstance().getMainWindow(), true );
738 		initialize();
739 	}
740 
741 
742 	/***
743 	 * 初期化処理を実行します。
744 	 */
745 	private void initialize()
746 	{
747 		_canvasManager = PekoSystem.getInstance().getCanvasManager();
748 		ClassLoader	cl = getClass().getClassLoader();
749 
750 		getContentPane().setLayout( new java.awt.FlowLayout() );
751 		JButton	button = new JButton();
752 		button.setIcon( new ImageIcon(cl.getResource("left-arrow.png")) );
753 		getContentPane().add( button );
754 		GenericListener.connect( button, this, ActionListener.class, "actionPerformed", "previous" );
755 		_previous = button;
756 		button.setEnabled( (_canvasManager.getPageHistoryCount() >= 1) );
757 
758 		button = new JButton();
759 		button.setIcon( new ImageIcon(cl.getResource("right-arrow.png")) );
760 		button.setEnabled( false );
761 		getContentPane().add( button );
762 		_next = button;
763 		GenericListener.connect( button, this, ActionListener.class, "actionPerformed", "next" );
764 
765 		pack();
766 		setResizable( false );
767 	}
768 
769 	/***
770 	 * 前のページを表示します。
771 	 */
772 	public void previous()
773 	{
774 		ResourceManager	resources = ResourceManager.getInstance();
775 		_index++;
776 		setTitle( ((MessageFormat)resources.getResource("peko.dialog.read-again.title-format")).format(new Object[]{String.valueOf(_index)}) );
777 		_next.setEnabled( (_index > 1 ) );
778 		if( _index == _canvasManager.getPageHistoryCount() )	{
779 			_previous.setEnabled( false );
780 		}
781 		_previous.setEnabled( _canvasManager.readAgain(_index) );
782 	}
783 
784 	/***
785 	 * 次のページを表示します。
786 	 */
787 	public void next()
788 	{
789 		ResourceManager	resources = ResourceManager.getInstance();
790 		_index--;
791 		setTitle( ((MessageFormat)resources.getResource("peko.dialog.read-again.title-format")).format(new Object[]{String.valueOf(_index)}) );
792 		_previous.setEnabled( true );
793 		if( _index == 1 )	{
794 			_next.setEnabled( false );
795 		}
796 		_canvasManager.readAgain( _index );
797 	}
798 
799 
800 //
801 //	JDialog の実装
802 //
803 	public void setVisible( boolean visible )
804 	{
805 		if( visible )	{
806 			_index = 0;
807 			if( _canvasManager.getPageHistoryCount() > 0 )	{
808 				previous();
809 			}
810 		}
811 		else	{
812 			_canvasManager.returnCurrent();
813 		}
814 		super.setVisible( visible );
815 	}
816 }