View Javadoc
1   /******************************************************************************
2    * CommandDispatcherImpl.java - Dispatch commands through the system
3    * $Id$
4    * 
5    * BuckoFIBS - Backgammon by BuckoSoft
6    * Copyright© 2009,2010 - Dick Balaska - BuckoSoft, Corp.
7    * 
8    * $Log$
9    * Revision 1.22  2011/07/04 03:42:37  dick
10   * writeGameErrorln() writes a message to the game window in red.
11   * onSavedMatch parses "No saved match" message.
12   *
13   * Revision 1.21  2011/06/22 05:54:46  dick
14   * writeChatMessageln is just a passthru now.
15   *
16   * Revision 1.20  2011/06/13 04:43:54  dick
17   * Echo all network out messages to the game window.
18   *
19   * Revision 1.19  2011/06/10 06:00:25  dick
20   * Set the tabs visible that we want when a game starts.
21   *
22   * Revision 1.18  2011/06/05 06:58:07  dick
23   * playerListPane becomes playerListTab.
24   *
25   * Revision 1.17  2011/05/23 05:53:54  dick
26   * Tell the GameManager when the user has sent his move to fibs.
27   *
28   * Revision 1.16  2011/05/22 22:58:59  dick
29   * GAME_MOVE becomes GAME_EVENT.
30   *
31   * Revision 1.15  2011/05/22 05:21:15  dick
32   * We don't need accept_or_decline_double anymore.  It's handled by the GameManager.
33   *
34   * Revision 1.14  2011/05/21 04:56:42  dick
35   * Work on integrating GUI game functions by routing them through the game manager now.
36   * Particularly, YourMove and ResumeGame.
37   *
38   * Revision 1.13  2011/05/14 04:43:01  dick
39   * I needed to deal with some lightweight Boards.
40   * So finally make the primary document Document
41   * and demote just the Board handling to a domain object.
42   *
43   * Revision 1.12  2011/05/13 15:05:46  dick
44   * GameLine becomes CookieString.
45   *
46   * Revision 1.11  2011/05/11 22:22:42  dick
47   * Working on animating moves.
48   *
49   * Revision 1.10  2011/05/10 16:08:20  dick
50   * Fix the javadoc pointers to the source code.
51   *
52   * Revision 1.9  2011/01/04 17:37:34  dick
53   * Disable the game gui if we are just watching.
54   *
55   * Revision 1.8  2010/12/29 07:46:59  dick
56   * Sorting dice is optional.
57   *
58   * Revision 1.7  2010/12/22 04:35:29  dick
59   * Add getMainDialog().
60   *
61   * Revision 1.6  2010/09/05 04:08:08  dick
62   * Version has to be a instantiated class.
63   *
64   * Revision 1.5  2010/03/03 13:12:21  inim
65   * Replaced (c) sign in comment mangled by CVS default encoding back to UTF-8
66   *
67   * Revision 1.4  2010/03/03 12:19:49  inim
68   * Moved source to UTF8 encoding from CP1252 encoding. To this end all source files' (c) message was updated to "Copyright© 2009,2010 - Dick Balaska - BuckoSoft, Corp.". This replaces the (c) sign to UTF8, and adds the new year 2010.
69   *
70   * Revision 1.3  2010/02/15 09:22:22  dick
71   * Play audio cues when Your opponent doubles or when he drops the match.
72   *
73   * Revision 1.2  2010/02/08 09:14:13  dick
74   * Add support for autoGreedyBearoff.  When the game turns to a race, enable greedy bearoffs.
75   *
76   * Revision 1.1  2010/02/04 05:57:53  inim
77   * Mavenized project folder layout
78   *
79   * Revision 1.32  2010/01/29 23:14:08  dick
80   * Handle the RatingsGraphConfigDialog.
81   *
82   * Revision 1.31  2010/01/25 21:07:57  dick
83   * Switch the chatPane to Kibitz when a match starts.
84   *
85   * Revision 1.30  2010/01/23 07:48:27  dick
86   * Turn off youInvited when a player's state changed.
87   *
88   * Revision 1.29  2010/01/23 06:15:08  dick
89   * Handle YOU_INVITED.
90   *
91   * Revision 1.28  2009/03/16 18:52:17  dick
92   * Play the YourTurn sound only if you can actually move.  (Respond to the "Please move" message.)
93   *
94   * Revision 1.27  2009/03/04 19:07:20  dick
95   * If you doubleclick on a player in the playerList, then generate a player report request.
96   *
97   * Revision 1.26  2009/03/01 09:11:56  dick
98   * ROP filtering is functional.
99   *
100  * Revision 1.25  2009/02/25 07:47:30  dick
101  * Move the Cue.YourMove sound to where you can actually move.  i.e. don't make noise when you can't move.
102  *
103  * Revision 1.24  2009/02/24 05:49:56  dick
104  * Handle state changes to the ROP flags.
105  *
106  * Revision 1.23  2009/02/20 10:22:47  dick
107  * Use YourName and OpponentName where possible, instead of just "getName".
108  * Temp development write a player to the database when we watch him.
109  *
110  * Revision 1.22  2009/02/16 06:57:31  dick
111  * Play a sound when it's your turn to roll or double.
112  *
113  * Revision 1.21  2009/02/14 13:08:01  dick
114  * BuckoFIBS is released under the GNU license.
115  * Get rid of unused Mode.
116  *
117  * Revision 1.20  2009/02/14 12:19:54  dick
118  * Add SHOW_ABOUT_DIALOG
119  *
120  * Revision 1.19  2009/02/12 06:25:48  dick
121  * Add BEAR_OFF and PLAY_CUE.
122  *
123  * Revision 1.18  2009/02/11 09:00:43  dick
124  * Better beginning and ending your turn.
125  * Send a 'who PL' if we get invited by an unknown player.
126  *
127  * Revision 1.17  2009/02/09 22:45:00  dick
128  * SEND_RESIGN to fibs.
129  *
130  * Revision 1.16  2009/02/06 07:56:48  dick
131  * Working on doubles.
132  *
133  * Revision 1.15  2009/02/03 09:45:59  dick
134  * Add some audio events.
135  * Setup ClientReceiveParser a little differently.
136  *
137  * Revision 1.14  2009/02/02 08:41:37  dick
138  * send a "board" command on match start, in case it was a resume.
139  *
140  * Revision 1.13  2009/02/01 21:24:34  dick
141  * Add onSavedMatch() and onMissManners() to track other players' behavior.
142  *
143  * Revision 1.12  2009/01/31 08:47:04  dick
144  * YourMove goes to the GameManager now.
145  * Handle Undo and Greedy buttons.
146  *
147  * Revision 1.11  2009/01/31 06:12:42  dick
148  * Handle dispatches for the GameManager.
149  * Handle button presses from the game toolbar.
150  *
151  * Revision 1.10  2009/01/28 19:11:42  dick
152  * FIBS' watch command doesn't take a parameter.
153  *
154  * Revision 1.9  2009/01/28 08:34:48  dick
155  * Empty the player list and the inviter list when we disconnect from FIBS.
156  *
157  * Revision 1.8  2009/01/27 19:15:01  dick
158  * Add onInviteWarning().
159  *
160  * Revision 1.7  2009/01/27 06:57:25  dick
161  * Handle the system uninviting us.
162  *
163  * Revision 1.6  2009/01/26 17:32:34  dick
164  * Set the clientConnection before setting the parser's mode.
165  *
166  * Revision 1.5  2009/01/24 17:05:40  dick
167  * Don't call yourMove when parsing the board here.
168  *
169  * Revision 1.4  2009/01/22 05:02:20  dick
170  * SEND_CHAT_COMMAND becomes the more generic SEND_COMMAND.
171  * onYourMove() doesn't need an argument.
172  *
173  * Revision 1.3  2009/01/18 06:38:25  dick
174  * RECEIVE_NETWORK_MESSAGE is obsolete.
175  *
176  * Revision 1.2  2009/01/18 06:18:09  dick
177  * State is private.
178  *
179  * Revision 1.1  2009/01/18 04:52:32  dick
180  * CommandDispatcher becomes CommandDispatcherImpl.
181  * CommandDispatcher is now the interface describing the API for the dispatcher.
182  *
183  * Revision 1.28  2009/01/16 07:28:00  dick
184  * Send a chat/command to the fibs server.
185  *
186  * Revision 1.27  2009/01/13 18:27:39  dick
187  * Handle Ready To Play
188  *
189  * Revision 1.26  2009/01/12 20:09:33  dick
190  * Set the FibsAttributes in the ClientConnection when initializing him.
191  *
192  * Revision 1.25  2009/01/10 05:04:17  dick
193  * Handle MATCH_OVER.
194  *
195  * Revision 1.24  2009/01/09 06:58:30  dick
196  * Chat message handling.
197  * ShowPrefs4Msgs dialog.
198  *
199  * Revision 1.23  2009/01/08 01:35:00  dick
200  * Update the entire board after parsing the fibs board string.
201  *
202  * Revision 1.22  2009/01/07 02:35:05  dick
203  * Generalize building a connection (commonize Connect vs. Register).
204  *
205  * Revision 1.21  2009/01/06 08:05:28  dick
206  * Handle registering a new user.
207  *
208  * Revision 1.20  2009/01/05 07:09:31  dick
209  * ConnectToServerDialog and CreateAccountDialog moved to account.
210  *
211  * Revision 1.19  2009/01/04 19:57:26  dick
212  * Add the create new account dialog.
213  *
214  * Revision 1.18  2008/12/20 23:02:10  dick
215  * Support for Own Info.
216  *
217  * Revision 1.17  2008/12/17 04:37:30  dick
218  * Cleanup Network Disconnect.
219  *
220  * Revision 1.16  2008/12/15 01:49:21  dick
221  * PlayerChanged goes to the list pane, not the model, so we update the count.
222  *
223  * Revision 1.15  2008/12/14 06:43:55  dick
224  * Watching switches to the boardpane.
225  *
226  * Revision 1.14  2008/12/13 06:57:11  dick
227  * Move ClientConnection, CookieMonster, and FIBSMessages to their own network package.
228  *
229  * Revision 1.13  2008/12/13 06:22:07  dick
230  * Handle NETWORK_CONNECT and NETWORK_DISCONNECT which twiddle some gui objects.
231  *
232  * Revision 1.12  2008/12/12 23:23:48  dick
233  * If writeSystemMessage is an error message, then make the system tab visible.
234  *
235  * Revision 1.11  2008/12/12 14:45:02  dick
236  * Add the WATCH handler.
237  *
238  * Revision 1.10  2008/12/11 20:28:21  dick
239  * Add AcceptInvitation, DeclineInvitation, StartGame, and Board.
240  *
241  * Revision 1.9  2008/12/11 09:59:24  dick
242  * Display all network received messages if user enabled.
243  *
244  * Revision 1.8  2008/12/11 08:47:09  dick
245  * Add showPreferencesDialog().
246  * Add inbound chat message handling.
247  *
248  * Revision 1.7  2008/12/10 18:01:58  dick
249  * Scroll the text pane to the bottom after outputting a message.
250  * Display system messages in color.
251  *
252  * Revision 1.6  2008/12/09 19:37:25  dick
253  * Handle being invited to a match.
254  *
255  * Revision 1.5  2008/12/09 01:49:46  dick
256  * writeNetworkMessage() allows us to send data back to the server.
257  *
258  * Revision 1.4  2008/04/09 20:57:07  dick
259  * Handle inviting a player to a match.
260  *
261  * Revision 1.3  2008/04/01 04:21:53  dick
262  * Handle player logging out.
263  *
264  * Revision 1.2  2008/03/31 07:09:42  dick
265  * Dispatching network messages.
266  *
267  * Revision 1.1  2008/03/30 05:40:50  dick
268  * Main command dispatcher for BuckoFIBS.
269  */
270 
271 /* 
272  * This program is free software: you can redistribute it and/or modify
273  * it under the terms of the GNU General Public License as published by
274  * the Free Software Foundation, either version 3 of the License, or
275  * (at your option) any later version.
276  *
277  * This program is distributed in the hope that it will be useful,
278  * but WITHOUT ANY WARRANTY; without even the implied warranty of
279  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
280  * GNU General Public License for more details.
281  *
282  * You should have received a copy of the GNU General Public License
283  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
284  *
285  * The Original Code is BuckoFIBS, <http://www.buckosoft.com/BuckoFIBS/>.
286  * The Initial Developer of the Original Code is Dick Balaska and BuckoSoft, Corp.
287  * 
288  */
289 package com.buckosoft.fibs.BuckoFIBS;
290 
291 import com.buckosoft.fibs.BuckoFIBS.AudioManager.Cue;
292 import com.buckosoft.fibs.BuckoFIBS.ClientReceiveParser.Mode;
293 import com.buckosoft.fibs.BuckoFIBS.gui.AboutDialog;
294 import com.buckosoft.fibs.BuckoFIBS.gui.MainDialog;
295 import com.buckosoft.fibs.BuckoFIBS.gui.PreferencesDialog;
296 import com.buckosoft.fibs.BuckoFIBS.gui.PreferencesForMessagesDialog;
297 import com.buckosoft.fibs.BuckoFIBS.gui.RatingGraphPanelConfigureDialog;
298 import com.buckosoft.fibs.BuckoFIBS.gui.SystemMessagesTextPane;
299 import com.buckosoft.fibs.BuckoFIBS.gui.account.ConnectToServerDialog;
300 import com.buckosoft.fibs.BuckoFIBS.gui.account.CreateAccountDialog;
301 import com.buckosoft.fibs.BuckoFIBS.gui.account.CreateAccountStatusInterface;
302 import com.buckosoft.fibs.BuckoFIBS.gui.chatWindow.ChatPane;
303 import com.buckosoft.fibs.domain.CookieString;
304 import com.buckosoft.fibs.domain.Player;
305 import com.buckosoft.fibs.domain.SavedMatch;
306 import com.buckosoft.fibs.domain.config.RatingGraphConfig;
307 import com.buckosoft.fibs.net.ClientConnection;
308 import com.buckosoft.fibs.net.FIBSMessages;
309 
310 /** Dispatch commands through the system.
311  * @author Dick Balaska
312  * @since 2008/03/30
313  * @version $Revision$ <br> $Date$
314  * @see <a href="http://cvs.buckosoft.com/Projects/BuckoFIBS/BuckoFIBS/src/main/java/com/buckosoft/fibs/BuckoFIBS/CommandDispatcherImpl.java">cvs CommandDispatcherImpl.java</a>
315  */
316 public class CommandDispatcherImpl implements CommandDispatcher, FIBSMessages {
317 	private	final static boolean DEBUG = false;
318 
319 	private	MainDialog		mainDialog;
320 	private	BFProperties	properties;
321 	private	ClientConnection	clientConnection = null;
322 
323 	private CreateAccountStatusInterface createAccountStatusInterface = null;
324 
325 	private	final static String eol = "\r\n";
326 
327 	/** Set the reference to the instance of MainDialog
328 	 * @param mainDialog The MainDialog that is running
329 	 */
330 	public	void setMainDialog(MainDialog mainDialog) {
331 		this.mainDialog = mainDialog;
332 	}
333 
334 	/** Fetch the reference to the MainDialog
335 	 * @return The MainDialog
336 	 */
337 	public MainDialog getMainDialog() {
338 		return(this.mainDialog);
339 	}
340 
341 	/** Set the Properties/User preferences
342 	 * @param properties The loaded properties
343 	 */
344 	public	void setProperties(BFProperties properties) {
345 		this.properties = properties;
346 	}
347 
348 	/** Get a reference to our properties
349 	 * @return The properties object
350 	 */
351 	public	BFProperties	getProperties() {
352 		return(this.properties);
353 	}
354 
355 	/** Primary entry point to the command dispatcher
356 	 * @param command The command to execute
357 	 */
358 	public void dispatch(Command command) {
359 		switch (command) {
360 		case SHOW_CONNECTION_DIALOG:
361 			onShowConnectionDialog();
362 			break;
363 		case SHOW_NEW_ACCOUNT_DIALOG:
364 			onShowNewAccountDialog();
365 			break;
366 		case DISCONNECT_FROM_NETWORK:
367 			onNetworkDisconnect();
368 			break;
369 		case CONNECT_TO_SERVER:
370 			onConnectToServer();
371 			break;
372 		case SHOW_PREFERENCES_DIALOG:
373 			onShowPreferencesDialog();
374 			break;
375 		case SHOW_PREFS4MSGS_DIALOG:
376 			onShowPrefs4MsgsDialog();
377 			break;
378 		case SHOW_RATINGS_GRAPH_DIALOG:
379 			onShowRatingGraphPanelConfigureDialog();
380 			break;
381 		case SHOW_ABOUT_DIALOG:
382 			onShowAboutDialog();
383 			break;
384 		case START_GAME:
385 			onStartGame();
386 			break;
387 		case RESUME_GAME:
388 			onResumeGame();
389 			break;
390 		case SHUTTING_DOWN:
391 			onShutdown();
392 			break;
393 		case NETWORK_CONNECTED:
394 			onNetworkConnected();
395 			break;
396 		case WATCHING:
397 			onWatching();
398 			break;
399 		case ROLL_OR_DOUBLE:
400 			onRollOrDouble();
401 			break;
402 		case TOGGLE_READY_TO_PLAY:
403 			onToggleReadyToPlay();
404 			break;
405 		case TOGGLE_GREEDY_BEAROFF:
406 			onToggleGreedyBearoff();
407 			break;
408 		case BEAR_OFF:
409 			this.mainDialog.getDocument().getBoard().clearDice();
410 			this.mainDialog.playSound(Cue.PickUpDice);
411 			this.mainDialog.youCantMove();		// you can't move because your turn is over
412 			break;
413 		case SEND_ROLL:
414 			this.writeNetworkMessageln("roll");		
415 // XXX:		this.mainDialog.getDocument().setYourTurnToRollOrDouble(false);
416 			this.mainDialog.updateBoard();
417 			break;
418 		case SEND_DOUBLE:
419 			this.writeNetworkMessageln("double");		
420 // XXX:		this.mainDialog.getDocument().setYourTurnToRollOrDouble(false);
421 			this.mainDialog.updateBoard();
422 			break;
423 		case SEND_ACCEPT:
424 			this.writeNetworkMessageln("accept");		
425 			break;
426 		case SEND_REJECT:
427 			this.writeNetworkMessageln("reject");		
428 			break;
429 			
430 		default:
431 			writeSystemMessageln("Dispatcher: Unhandled command " + command);
432 			throw new RuntimeException("Unhandled command " + command);
433 		}
434 	}
435 
436 	/** Primary entry point to the command dispatcher
437 	 * what takes a single string as an argument
438 	 * @param command The Command to Execute
439 	 * @param arg1 A string that the dispatched function wants
440 	 */
441 	public void dispatch(Command command, String arg1) {
442 		switch (command) {
443 		case SYSTEM_MESSAGE:
444 			writeSystemMessage(arg1);
445 			break;
446 /*		case RECEIVE_NETWORK_MESSAGE:
447 			if (this.properties.isDisplayRecv())
448 				writeSystemMessageln(SystemMessagesTextPane.NETWORKIN, arg1);
449 			this.clientReceiveParser.parseMessage(arg1);
450 			break;
451 */
452 		case PLAYER_GONE:
453 			this.mainDialog.getPlayerListTab().playerGone(arg1);
454 			this.mainDialog.getInviterTableModel().uninvited(arg1);
455 			break;
456 		case SAVED_MATCH:
457 			onSavedMatch(arg1);
458 			break;
459 		case MISS_MANNERS:
460 			onMissManners(arg1);
461 			break;
462 		case WATCH:
463 			onWatch(arg1);
464 			break;
465 		case GET_PLAYER_REPORT:
466 			onGetPlayerReport(arg1);
467 			break;
468 		case ACCEPT_INVITATION:
469 			onAcceptInvitation(arg1);
470 			this.mainDialog.getInviterTableModel().uninvited(arg1);
471 			this.mainDialog.setGameMessagesTabVisible();
472 			this.mainDialog.setBoardTabVisible();
473 			break;
474 		case UNINVITED:
475 			onUninvited(arg1);
476 			break;
477 		case YOU_INVITED:
478 			this.onYouInvited(arg1);
479 			break;
480 		case OWN_INFO:
481 			parseOwnInfo(arg1);
482 			break;
483 //		case FIBS_BOARD:
484 //			parseFibsBoard(arg1);
485 //			break;
486 		case DOUBLE:
487 			break;
488 //		case YOUR_MOVE:
489 //			onYourMove(Integer.parseInt(arg1));
490 //			break;
491 		case BAD_NEW_USER:
492 			this.createAccountStatusInterface.setStatus(arg1);
493 			this.createAccountStatusInterface.onRegisterFailure();
494 			break;
495 		case SEND_RESIGN:
496 			this.writeNetworkMessageln("resign " + arg1);
497 			break;
498 		case SEND_MOVE:
499 			this.mainDialog.getGameManager().youMoved();
500 			this.writeNetworkMessageln(arg1);
501 			break;
502 		case SEND_COMMAND:
503 			this.writeNetworkMessageln(arg1);		
504 			break;
505 		default:
506 			writeSystemMessageln("Dispatcher: Unhandled command " + command);
507 			throw new RuntimeException("Unhandled command " + command);
508 		}
509 	}
510 
511 	/** Primary entry point to the command dispatcher
512 	 * what takes two strings as an argument
513 	 * @param command The Command to Execute
514 	 * @param arg1 A string that the dispatched function wants
515 	 * @param arg2 Another string that the dispatched function wants
516 	 */
517 	public void dispatch(Command command, String arg1, String arg2) {
518 		switch (command) {
519 		case INVITED:
520 			onInvited(arg1, arg2);
521 			break;
522 		case INVITE:
523 			onInvite(arg1, arg2);
524 			break;
525 		case INVITE_WARNING:
526 			onInviteWarning(arg1, arg2);
527 			break;
528 		case MATCH_OVER:
529 			this.mainDialog.onMatchOver(arg1, arg2);
530 			break;
531 		default:
532 			writeSystemMessageln("Dispatcher: Unhandled command " + command);
533 			throw new RuntimeException("Unhandled command" + command);
534 		}
535 	}
536 
537 	/** Primary entry point to the command dispatcher
538 	 * what takes an Object as an argument
539 	 * @param command The Command to Execute
540 	 * @param obj An Object that the dispatched function wants
541 	 */
542 	public void dispatch(Command command, Object obj) {
543 		boolean b;
544 		switch (command) {
545 		case GAME_EVENT:
546 			this.mainDialog.getGameManager().addEvent((CookieString)obj);
547 			break;
548 		case PLAYER_CHANGED:
549 			onPlayerChanged((Player)obj);
550 			break;
551 		case REGISTER_NEW_USER:
552 			createAccountStatusInterface = (CreateAccountStatusInterface)obj;
553 			onRegisterNewUser();
554 			break;
555 		case READY_TO_PLAY:
556 			b = (Boolean)obj;
557 			this.mainDialog.setReadyToPlay(b);
558 			if (!b)
559 				onYouInvited(null);
560 			break;
561 		case TOGGLE_DOUBLE:
562 			b = (Boolean)obj;
563 			this.mainDialog.setAskDouble(b);
564 			break;
565 		case PLAY_CUE:
566 			AudioManager.Cue cue = (AudioManager.Cue)obj;
567 			this.mainDialog.playSound(cue);
568 			break;
569 		case SET_RATING_GRAPH_CONFIG:
570 			RatingGraphConfig rgc = (RatingGraphConfig)obj;
571 			this.mainDialog.getToolbar().getRatingGraphPanel().setConfig(rgc);
572 			this.mainDialog.getToolbar().getRatingGraphPanel().redraw();
573 			break;
574 		default:
575 			writeSystemMessageln("Dispatcher: Unhandled command " + command);
576 			throw new RuntimeException("Unhandled command" + command);
577 		}
578 	}
579 
580 	/** Write a message to the System message pane in the normal color
581 	 * @param s The message to write
582 	 */
583 	public	void writeSystemMessage(String s) {
584 		this.mainDialog.getSystemMessagesTextPane().appendMessage(s);
585 		this.mainDialog.systemMessagesScrollToBottom();
586 	}
587 	
588 	/** Write a message to the System message pane in the normal color.
589 	 * Terminate the message with a crlf.
590 	 * @param s The message to write
591 	 */
592 	public void writeSystemMessageln(String s) {
593 		this.mainDialog.getSystemMessagesTextPane().appendMessage(s + eol);		
594 		this.mainDialog.systemMessagesScrollToBottom();
595 	}
596 
597 	/** Write a message to the status widget in the registerUser dialog
598 	 * @param s The message to write
599 	 */
600 	public void writeRegisterUserMessage(String s) {
601 		if (this.createAccountStatusInterface != null)
602 			this.createAccountStatusInterface.setStatus(s);
603 	}
604 
605 	/** Write a message to the System message pane in the specified color.
606 	 * @param type The style of the text
607 	 * @param s The message to write
608 	 */
609 	public void writeSystemMessage(int type, String s) {
610 		this.mainDialog.getSystemMessagesTextPane().appendMessage(type, s);		
611 		this.mainDialog.systemMessagesScrollToBottom();
612 	}
613 
614 	/** Write a message to the System message pane in the specified color.
615 	 * Terminate the message with a crlf.
616 	 * @param type The style of the text
617 	 * @param s The message to write
618 	 */
619 	public void writeSystemMessageln(int type, String s) {
620 		this.mainDialog.getSystemMessagesTextPane().appendMessage(type, s + eol);		
621 		this.mainDialog.systemMessagesScrollToBottom();
622 		if (type == SystemMessagesTextPane.ERROR)
623 			this.mainDialog.setSystemMessagesTabVisible();
624 	}
625 
626 	/** Write a message to the chat message pane in the normal color.
627 	 * Terminate the message with a crlf.
628 	 * @param name The user what sent the message
629 	 * @param cookie The mode used to send the message (shout, whisper, kibitz, etc)
630 	 * @param text The message to write
631 	 */
632 	public void writeChatMessageln(String name, int cookie, String text) {
633 		this.mainDialog.addChatMessage(name, cookie, text);
634 	}
635 
636 	@Override
637 	public void writeGameMessageln(String s) {
638 		this.mainDialog.writeGameMessageln(s);
639 	}
640 	
641 	@Override
642 	public void writeGameErrorln(String s) {
643 		this.mainDialog.writeGameMessageln(SystemMessagesTextPane.ERROR, s);
644 	}
645 
646 	/** Send a message to the fibs server
647 	 * @param s The message to send
648 	 * @return success
649 	 */
650 	public boolean writeNetworkMessage(String s) {
651 		if (this.clientConnection != null) {
652 			this.clientConnection.sendMessage(s);
653 			return(true);
654 		} else 
655 			return(false);
656 	}
657 	
658 	/** Send a message to the fibs server appending a crlf to the end
659 	 * @param s The message to send
660 	 * @return success
661 	 */
662 	public boolean writeNetworkMessageln(String s) {
663 		this.mainDialog.writeGameMessageln(SystemMessagesTextPane.NETWORKOUT, s);
664 		return(this.writeNetworkMessage(s + eol));
665 	}
666 
667 	private	void onShowConnectionDialog() {
668 		ConnectToServerDialog dialog = new ConnectToServerDialog(mainDialog, this);
669 		dialog.setVisible(true);
670 	}
671 
672 	private	void onShowNewAccountDialog() {
673 		CreateAccountDialog dialog = new CreateAccountDialog(mainDialog, this);
674 		dialog.setVisible(true);
675 	}
676 
677 	private	void onConnectToServer() {
678 		if (createAccountStatusInterface != null) {
679 			createAccountStatusInterface.onRegisterSuccess();
680 			createAccountStatusInterface = null;
681 		}
682 		startClientConnection(Mode.Run);
683 	}
684 
685 	private void onRegisterNewUser() {
686 		int profileId = this.properties.getSelectedProfile();
687 		String s = "Connecting to "
688 			+ this.properties.getServerName(profileId)
689 			+ ":"
690 			+ this.properties.getServerPort(profileId);
691 		this.createAccountStatusInterface.setStatus(s);
692 		startClientConnection(Mode.Register);
693 	}
694 
695 	private void startClientConnection(Mode mode) {
696 		if (this.clientConnection != null) {
697 			if (DEBUG)
698 				System.out.println("Tear down old ClientConnection");
699 			this.clientConnection.shutDown();
700 			this.clientConnection = null;
701 		}
702 		if (DEBUG)
703 			System.out.println("Create new ClientConnection");
704 		this.clientConnection = new ClientConnection();
705 		ClientReceiveParser clientReceiveParser = this.mainDialog.getClientReceiveParser();
706 		this.clientConnection.setClientAdapter(clientReceiveParser);
707 		this.clientConnection.setFibsAttributes(properties);
708 		clientReceiveParser.setClientConnection(this.clientConnection);
709 		clientReceiveParser.setMode(mode);
710 		this.clientConnection.start();
711 	}
712 
713 	private void onShowPreferencesDialog() {
714 		PreferencesDialog dialog = new PreferencesDialog(mainDialog, this);
715 		dialog.setVisible(true);
716 	}
717 
718 	private void onShowAboutDialog() {
719 		AboutDialog aboutDialog = new AboutDialog(mainDialog);
720 		aboutDialog.setVersion(Version.getVersion());
721 		aboutDialog.setVisible(true);
722 	}
723 	private void onShowPrefs4MsgsDialog() {
724 		PreferencesForMessagesDialog dialog = new PreferencesForMessagesDialog(mainDialog, this);
725 		dialog.setVisible(true);
726 	}
727 
728 	private void onShowRatingGraphPanelConfigureDialog() {
729 		RatingGraphPanelConfigureDialog dialog = new RatingGraphPanelConfigureDialog(mainDialog, this);
730 		dialog.setVisible(true);
731 		// modal dialog happens here
732 		this.mainDialog.getToolbar().getRatingGraphPanel().setConfig(this.properties.getRatingGraphConfig());
733 		this.mainDialog.updateRatingPanel();
734 	}
735 
736 	private	void onShutdown() {
737 		onNetworkDisconnect();
738 	}
739 
740 	private void onNetworkConnected() {
741 		this.writeNetworkMessageln("set boardstyle 3");
742 		this.mainDialog.setConnected(true);
743 	}
744 
745 	private	void onNetworkDisconnect() {
746 		if (this.clientConnection != null) {
747 			this.clientConnection.shutDown();
748 			this.clientConnection = null;
749 		}
750 		this.mainDialog.setConnected(false);
751 		this.mainDialog.getInviterTableModel().removeAll();
752 		this.mainDialog.getPlayerTableModel().removeAll();
753 	}
754 
755 	private void onPlayerChanged(Player p) {
756 		p.setSavedMatch(this.mainDialog.getDocument().getSavedMatchString(p.getName()));
757 		p.setMissManners(this.mainDialog.getDocument().getMissMannersString(p.getName()));
758 		p.setInvited(false);				// a player state change clears his invited flag
759 		this.mainDialog.getDB().updateOpponent(p);
760 		this.mainDialog.getPlayerListTab().playerChanged(p);
761 		if (p.getOpponent().length() > 0)	// If he is playing, then any invite of his is dead.
762 			onUninvited(p.getName());
763 		this.mainDialog.getInviterTableModel().playerChanged(p);
764 		if (p.getName().equals(this.properties.getUserName())) {
765 			this.mainDialog.getDocument().setReady(p.isReady());
766 			this.mainDialog.redrawOwnInfo();
767 		}
768 	}
769 
770 	private	void onInvite(String playerName, String length) {
771 		this.writeNetworkMessageln("invite " + playerName + " " + length);
772 	}
773 
774 	private	void onSavedMatch(String s) {
775 		String[] ss = s.split(" ");
776 		if (ss[2].equals("no")) {
777 			ss = ss[6].split("\\.");
778 			Player p = this.mainDialog.getPlayerTableModel().getPlayer(ss[0]);
779 			if (p != null) {
780 				p.setSavedMatch(null);
781 				this.mainDialog.getPlayerListTab().playerChanged(p);
782 			}
783 			return;
784 		}
785 		SavedMatch sm = this.mainDialog.getDocument().parseSavedMatch(s);
786 		Player p = this.mainDialog.getPlayerTableModel().getPlayer(sm.getOpponentName());
787 		if (p != null) {
788 			p.setSavedMatch(this.mainDialog.getDocument().getSavedMatchString(p.getName()));
789 			this.mainDialog.getPlayerListTab().playerChanged(p);
790 		}
791 	}
792 
793 	private	void onMissManners(String s) {
794 		SavedMatch sm = this.mainDialog.getDocument().parseMissManners(s);
795 		if (sm == null)
796 			return;
797 		Player p = this.mainDialog.getPlayerTableModel().getPlayer(sm.getOpponentName());
798 		if (p != null) {
799 			p.setMissManners(this.mainDialog.getDocument().getSavedMatchString(p.getName()));
800 			this.mainDialog.getPlayerListTab().playerChanged(p);
801 		}
802 	}
803 
804 	private void onGetPlayerReport(String playerName) {
805 		this.mainDialog.getPlayerReportPane().setPlayer(playerName);
806 	}
807 
808 	private	void onWatch(String playerName) {
809 		this.writeNetworkMessageln("watch " + playerName);
810 
811 		if (playerName == "NoSuchPlayerToMatchTo") {
812 			// temp database development...
813 			Player p;
814 			p = this.mainDialog.getPlayerTableModel().getPlayer(playerName);
815 			Player p1;
816 			p1 = this.mainDialog.getDB().getPlayer(playerName);
817 			if (p1 == null)
818 				this.mainDialog.getDB().store(p);
819 			System.out.println("playerId = " + p.getId());
820 		}
821 	}
822 
823 	private	void onAcceptInvitation(String playerName) {
824 		this.writeNetworkMessageln("join " + playerName);
825 	}
826 
827 	private	void onRollOrDouble() {
828 		this.mainDialog.getGameManager().onRollOrDouble();
829 	}
830 
831 	private void onToggleReadyToPlay() {
832 		this.writeNetworkMessageln("toggle ready");
833 	}
834 
835 	private void onToggleGreedyBearoff() {
836 		this.writeNetworkMessageln("toggle greedy");
837 		this.mainDialog.getDocument().setGreedy(!this.mainDialog.getDocument().isGreedy());
838 	}
839 
840 	private void onInvited(String playerName, String matchLength) {
841 		Player p = this.mainDialog.getPlayerTableModel().getPlayer(playerName);
842 		if (p == null) {
843 			this.writeSystemMessageln(SystemMessagesTextPane.ERROR, 
844 					"Unknown player '" + playerName + "' tried to invite you");
845 			p = new Player();
846 			p.setName(playerName);
847 			this.dispatch(CommandDispatcher.Command.PLAYER_CHANGED, p);
848 			this.writeNetworkMessageln("who " + playerName);
849 		}
850 		this.mainDialog.playSound(Cue.Invited);
851 		this.mainDialog.getInviterTableModel().invited(p, matchLength);
852 		this.mainDialog.setInvitedTabVisible();
853 	}
854 
855 	private	void onInviteWarning(String playerName, String warning) {
856 		this.mainDialog.getInviterTableModel().setWarning(playerName, warning);		
857 	}
858 
859 	private void onUninvited(String playerName) {
860 		this.mainDialog.getInviterTableModel().uninvited(playerName);
861 	}
862 
863 	private	void onYouInvited(String playerName) {
864 		this.mainDialog.getPlayerListTab().playerInvited(playerName);
865 	}
866 
867 	private void onStartGame() {
868 		this.mainDialog.getDocument().resetGame();
869 		this.mainDialog.getDocument().getBoard().setSortDice(this.properties.isHighDieLeft());
870 		this.mainDialog.redrawOwnInfo();
871 		this.mainDialog.setBoardTabVisible();
872 		//this.writeNetworkMessageln("board");
873 		this.mainDialog.getChatPane().setupComboBoxCommand(ChatPane.Command.Kibitz);
874 	}
875 	
876 	/* XXX: This is stupid, resume is the same as start, but with a board command? */
877 	private void onResumeGame() {
878 		this.mainDialog.getGameManager().reset(true);
879 		this.mainDialog.getDocument().resetGame();
880 		this.mainDialog.getDocument().getBoard().setSortDice(this.properties.isHighDieLeft());
881 		this.mainDialog.redrawOwnInfo();
882 		this.mainDialog.setBoardTabVisible();
883 		this.writeNetworkMessageln("board");
884 		this.mainDialog.getChatPane().setupComboBoxCommand(ChatPane.Command.Kibitz);
885 	}
886 
887 	private	void onWatching() {
888 		this.mainDialog.getGameManager().reset(false);
889 		this.mainDialog.getDocument().resetGame();
890 		this.mainDialog.getBoardTab().getBoardGui().youCantMove();
891 		this.mainDialog.getDocument().getBoard().setSortDice(this.properties.isHighDieLeft());
892 //		this.mainDialog.redrawOwnInfo();
893 		this.mainDialog.setBoardTabVisible();
894 		this.writeNetworkMessageln("board");
895 		this.mainDialog.getChatPane().setupComboBoxCommand(ChatPane.Command.Kibitz);
896 		//this.writeNetworkMessageln("board");
897 	}
898 
899 	
900 //	private void onYourMove(int diceToMove) {
901 // XXX:	this.mainDialog.getDocument().setYourTurnToRollOrDouble(false);
902 //		this.mainDialog.getDocument().getBoard().setSortDice(this.properties.isHighDieLeft());
903 //		this.mainDialog.getGameManager().yourMove(diceToMove);
904 //	}
905 
906 /*	private	void parseFibsBoard(String board) {
907 		this.mainDialog.getDocument().getBoard().parseFibsBoard(board);
908 		this.mainDialog.updateBoard();
909 //		if (this.mainDialog.getBoard().getWhosTurn() == -1)
910 //			this.mainDialog.yourMove();
911 	}
912 */
913 	private void parseOwnInfo(String s) {
914 		this.mainDialog.getDocument().parseOwnInfo(s);
915 		if (this.properties.isFibsReadyToPlay() != this.mainDialog.getDocument().isReady())
916 			this.writeNetworkMessageln("toggle ready");
917 		else
918 			this.mainDialog.setReadyToPlay(this.properties.isFibsReadyToPlay());
919 		this.mainDialog.redrawOwnInfo();
920 	}
921 
922 	/* (non-Javadoc)
923 	 * @see com.buckosoft.fibs.BuckoFIBS.gui.board.ToolbarHandler#buttonPressed(com.buckosoft.fibs.BuckoFIBS.gui.board.ToolbarHandler.Button)
924 	 */
925 	@Override
926 	public void buttonPressed(Button button) {
927 		if (button == Button.First)
928 			this.mainDialog.getGameManager().goFirst();
929 		else if (button == Button.Prev)
930 			this.mainDialog.getGameManager().goPrev();
931 		else if (button == Button.Next)
932 			this.mainDialog.getGameManager().goNext();
933 		else if (button == Button.Last)
934 			this.mainDialog.getGameManager().goLast();
935 		else if (button == Button.Undo)
936 			this.mainDialog.getGameManager().goUndo();
937 		else if (button == Button.PlayPaused)
938 			this.mainDialog.getGameManager().goPlayPaused();
939 		else if (button == Button.Greedy)
940 			onToggleGreedyBearoff();
941 		else if (button == Button.AskDoubles)
942 			this.writeNetworkMessageln("toggle double");
943 		else if (button == Button.Resign)
944 			this.mainDialog.showResignOutDialog();
945 	}
946 
947 	/* (non-Javadoc)
948 	 * @see com.buckosoft.fibs.BuckoFIBS.CommandDispatcher#ropChanged(boolean[])
949 	 */
950 	@Override
951 	public void ropChanged(boolean[] rop) {
952 		this.properties.setROP(rop);
953 		this.mainDialog.getPlayerListTab().setROP(rop);
954 	}
955 
956 }