View Javadoc
1   /******************************************************************************
2    * PlayerListPane.java - Display the list of players in a panel with buttons and scrollbars and everything.
3    * $Id$
4    * 
5    * BuckoFIBS - Backgammon by BuckoSoft
6    * Copyright© 2009,2010 - Dick Balaska - BuckoSoft, Corp.
7    * 
8    * $Log$
9    * Revision 1.9  2011/01/04 17:39:52  dick
10   * When a popup menu item is selected, use the player that was selected when the menu opened,
11   * not who is there now.
12   *
13   * Revision 1.8  2011/01/01 20:45:50  dick
14   * Update the group text box on changes.
15   *
16   * Revision 1.7  2011/01/01 06:11:55  dick
17   * Run the filters through the GroupManager.
18   *
19   * Revision 1.6  2011/01/01 01:26:24  dick
20   * Rebuild the group menu when displaying the popup.
21   *
22   * Revision 1.5  2010/12/31 05:30:58  dick
23   * Add support for displaying the GroupSelectPane and friends.
24   *
25   * Revision 1.4  2010/12/30 04:10:51  dick
26   * Bug 8 - Shouldn't be able to invite players that are already playing.
27   *
28   * Revision 1.3  2010/03/03 13:12:21  inim
29   * Replaced (c) sign in comment mangled by CVS default encoding back to UTF-8
30   *
31   * Revision 1.2  2010/03/03 12:19:49  inim
32   * 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.
33   *
34   * Revision 1.1  2010/02/04 05:57:53  inim
35   * Mavenized project folder layout
36   *
37   * Revision 1.12  2010/01/25 02:54:43  dick
38   * Use the selected index at the time the right mouse was clicked.
39   *
40   * Revision 1.11  2010/01/24 06:21:36  dick
41   * Don't update the playerList if the popupmenu is open, it gets confused.
42   *
43   * Revision 1.10  2010/01/23 07:48:49  dick
44   * Turn off youInvited when a player's state changed.
45   *
46   * Revision 1.9  2010/01/23 06:25:20  dick
47   * Add repbot and playerInvited handling.
48   *
49   * Revision 1.8  2009/03/12 16:36:17  dick
50   * Move the double-click test above, so we check for a valid player.
51   *
52   * Revision 1.7  2009/03/04 19:04:45  dick
53   * Get the row filter working.
54   * If you doubleclick on a player, then generate a player report request.
55   *
56   * Revision 1.6  2009/03/01 09:11:56  dick
57   * ROP filtering is functional.
58   *
59   * Revision 1.5  2009/02/24 08:05:42  dick
60   * Try filtering rows based on ROP.  DDS.
61   *
62   * Revision 1.4  2009/02/17 14:44:50  dick
63   * Turn off DEBUG.
64   *
65   * Revision 1.3  2009/02/14 15:46:36  dick
66   * BuckoFIBS is released under the GNU license.
67   *
68   * Revision 1.2  2009/02/01 21:28:00  dick
69   * Add the invite submenu.
70   *
71   * Revision 1.1  2009/01/28 19:39:44  dick
72   * package com.buckosoft.fibs.gui.playerList becomes com.buckosoft.fibs.BuckoFIBS.gui.playerList.
73   *
74   * Revision 1.7  2009/01/22 05:06:30  dick
75   * Add sorting and variable column widths.
76   *
77   * Revision 1.6  2008/12/15 01:50:53  dick
78   * Display the number of players in the list.
79   *
80   * Revision 1.5  2008/12/12 14:46:49  dick
81   * Handle the Watch command.
82   *
83   * Revision 1.4  2008/12/11 20:34:36  dick
84   * Javadoc.
85   *
86   * Revision 1.3  2008/04/09 20:58:04  dick
87   * Handle inviting a player to a match.
88   *
89   * Revision 1.2  2008/04/07 08:12:33  dick
90   * Add the popup menu to the PlayerList.
91   *
92   * Revision 1.1  2008/04/02 23:22:53  dick
93   * Move playerList to it's own package.
94   *
95   * Revision 1.1  2008/04/01 03:45:14  dick
96   * Display the list of players in a panel with buttons and scrollbars and everything.
97   */
98  
99  /* 
100  * This program is free software: you can redistribute it and/or modify
101  * it under the terms of the GNU General Public License as published by
102  * the Free Software Foundation, either version 3 of the License, or
103  * (at your option) any later version.
104  *
105  * This program is distributed in the hope that it will be useful,
106  * but WITHOUT ANY WARRANTY; without even the implied warranty of
107  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108  * GNU General Public License for more details.
109  *
110  * You should have received a copy of the GNU General Public License
111  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
112  *
113  * The Original Code is BuckoFIBS, <http://www.buckosoft.com/BuckoFIBS/>.
114  * The Initial Developer of the Original Code is Dick Balaska and BuckoSoft, Corp.
115  * 
116  */
117 package com.buckosoft.fibs.BuckoFIBS.gui.playerList;
118 
119 import java.awt.ComponentOrientation;
120 import java.awt.Dimension;
121 import java.awt.GridBagConstraints;
122 import java.awt.GridBagLayout;
123 import java.awt.Insets;
124 import java.awt.Point;
125 import java.awt.event.ActionEvent;
126 import java.awt.event.ActionListener;
127 import java.awt.event.KeyEvent;
128 import java.awt.event.MouseAdapter;
129 import java.awt.event.MouseEvent;
130 
131 import javax.swing.ImageIcon;
132 import javax.swing.JLabel;
133 import javax.swing.JPanel;
134 import javax.swing.JScrollPane;
135 import javax.swing.JTable;
136 import javax.swing.JTextField;
137 import javax.swing.JToggleButton;
138 import javax.swing.JToolBar;
139 import javax.swing.ListSelectionModel;
140 import javax.swing.RowFilter;
141 import javax.swing.table.TableRowSorter;
142 
143 import com.buckosoft.fibs.BuckoFIBS.CommandDispatcher;
144 import com.buckosoft.fibs.BuckoFIBS.GroupManager;
145 import com.buckosoft.fibs.BuckoFIBS.gui.MainDialog;
146 import com.buckosoft.fibs.BuckoFIBS.gui.playerList.group.GroupSelectPane;
147 import com.buckosoft.fibs.domain.Player;
148 import java.awt.Font;
149 
150 /** Display the list of Players
151  * @author Dick Balaska
152  * @since 2008/04/01
153  * @version $Revision$ <br> $Date$
154  * @see <a href="http://cvs.buckosoft.com/Projects/BuckoFIBS/BuckoFIBS/src/main/java/com/buckosoft/fibs/BuckoFIBS/gui/playerList/PlayerListPane.java">cvs PlayerListPane.java</a>
155  */
156 public class PlayerListPane extends JPanel implements ActionListener {
157 	private	final static boolean DEBUG = false;
158 	private static final long serialVersionUID = 1L;
159 	private JToolBar jToolBar = null;
160 	private JScrollPane playerListScrollPane = null;
161 	private JToggleButton readyToggleButton = null;
162 	private JToggleButton onlineToggleButton = null;
163 	private JToggleButton playingToggleButton = null;
164 
165 	private JTable			playerListTable = null;
166 	private	PlayerTableModel playerTableModel;
167 
168 	private	PlayerListPopupMenu playerListPopupMenu = null;
169 	private	CommandDispatcher	commandDispatcher = null;
170 	private	GroupManager		groupManager;
171 	private GroupSelectPane		groupPane;
172 	private	MainDialog			mainDialog;
173 
174 	/** Count of the number of players logged in */
175 	private JLabel jLabelLoggedIn = null;
176 
177 	/** Filter on Ready/Online/Playing */
178 	private	boolean[] rop = new boolean[] {false, false, false};
179 
180 	private	boolean	updateLocked = false;
181 	//private	int		selectedIndex = -2;
182 
183 	/** This is the default constructor
184 	 */
185 	public PlayerListPane() {
186 		super();
187 		initialize();
188 	}
189 
190 	public PlayerTableModel getPlayerTableModel() {
191 		return(playerTableModel);
192 	}
193 
194 	public void setCommandDispatcher(CommandDispatcher commandDispatcher) {
195 		this.commandDispatcher = commandDispatcher;
196 	}
197 
198 	public void setGroupManager(GroupManager groupManager) {
199 		this.groupManager = groupManager;
200 		playerListPopupMenu.setGroupManager(groupManager);
201 		this.groupManager.setPlayerListPane(this);
202 		groupPaneChanged();
203 	}
204 
205 	public void setMainDialog(MainDialog mainDialog) {
206 		this.mainDialog = mainDialog;
207 	}
208 
209 	/** Return the Player in the table that matches this name.
210 	 * @param playerName The name to query
211 	 * @return The Player found or null if no match
212 	 */
213 	public Player getPlayer(String playerName) {
214 		return(this.playerTableModel.getPlayer(playerName));
215 	}
216 
217 	public void playerChanged(Player player) {
218 		this.playerTableModel.playerChanged(player);
219 		if (!this.updateLocked) {
220 			updatePlayerCount();
221 			playerListTable.setRowSorter(sorter);
222 			sorter.setRowFilter(rowFilter);
223 		}
224 	}
225 
226 	public void playerGone(String playerName) {
227 		this.playerTableModel.playerGone(playerName);
228 		if (!this.updateLocked) {
229 			updatePlayerCount();
230 			playerListTable.setRowSorter(sorter);
231 			sorter.setRowFilter(rowFilter);
232 		}
233 	}
234 
235 	/** Turn on the "you invited" icon for a player.
236 	 * Note that you only get one open invite. 
237 	 * @param playerName
238 	 */
239 	public void playerInvited(String playerName) {
240 		if (playerName == null)
241 			playerUninvited();
242 		else {
243 			this.playerTableModel.playerInvited(playerName);
244 			if (!this.updateLocked) {
245 				updatePlayerCount();
246 				playerListTable.setRowSorter(sorter);
247 				sorter.setRowFilter(rowFilter);
248 			}
249 		}
250 	}
251 
252 	private void playerUninvited() {
253 		if (this.playerTableModel.playerUninvited()) {
254 			if (!this.updateLocked) {
255 				updatePlayerCount();
256 				playerListTable.setRowSorter(sorter);
257 				sorter.setRowFilter(rowFilter);
258 			}
259 		}
260 	}
261 	/** Set the states of the Ready, Online, and Playing buttons.
262 	 * @param rop The state of the Ready, Online, and Playing buttons.
263 	 */
264 	public void setROP(boolean[] rop) {
265 		this.readyToggleButton.setSelected(rop[0]);
266 		this.onlineToggleButton.setSelected(rop[1]);
267 		this.playingToggleButton.setSelected(rop[2]);
268 		this.rop = rop;
269 		playerListTable.setRowSorter(sorter);
270 		sorter.setRowFilter(rowFilter);
271 		sorter.sort();
272 	}
273 
274 	/**
275 	 * This method initializes this
276 	 * 
277 	 * @return void
278 	 */
279 	private void initialize() {
280 		getPlayerListPopupMenu();
281 		GridBagConstraints gridBagConstraints5 = new GridBagConstraints();
282 		gridBagConstraints5.gridx = 1;
283 		gridBagConstraints5.weightx = 0.1;
284 		gridBagConstraints5.gridy = 0;
285 		GridBagConstraints gridBagConstraints11 = new GridBagConstraints();
286 		gridBagConstraints11.gridx = 2;
287 		gridBagConstraints11.insets = new Insets(0, 0, 0, 13);
288 		gridBagConstraints11.weightx = 0.2;
289 		gridBagConstraints11.gridy = 0;
290 		GridBagConstraints gridBagConstraints1 = new GridBagConstraints();
291 		gridBagConstraints1.fill = GridBagConstraints.BOTH;
292 		gridBagConstraints1.gridy = 1;
293 		gridBagConstraints1.weightx = 1.0;
294 		gridBagConstraints1.weighty = 1.0;
295 		gridBagConstraints1.gridwidth = 3;
296 		gridBagConstraints1.gridx = 0;
297 		GridBagConstraints gridBagConstraints = new GridBagConstraints();
298 		gridBagConstraints.fill = GridBagConstraints.BOTH;
299 		gridBagConstraints.gridy = 0;
300 		gridBagConstraints.weightx = 1.0;
301 		gridBagConstraints.anchor = GridBagConstraints.WEST;
302 		gridBagConstraints.gridx = 0;
303 		this.setSize(300, 200);
304 		this.setLayout(new GridBagLayout());
305 		this.add(getJToolBar(), gridBagConstraints);
306 		jLabelLoggedIn = new JLabel();
307 		jLabelLoggedIn.setText("On:");
308 		this.add(getPlayerListScrollPane(), gridBagConstraints1);
309 		this.add(getJPanelDummyAfterGroup(), gridBagConstraints5);
310 		this.add(jLabelLoggedIn, gridBagConstraints11);
311 	}
312 
313 	
314 	/** Called directly from the menu.
315 	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
316 	 */
317 	public void actionPerformed(ActionEvent e) {
318 		if (e.getActionCommand().equals(PlayerListPopupMenu.s_setVisible)) {
319 			this.updateLocked = e.getModifiers() == 0 ? false : true;
320 			if (!this.updateLocked) {
321 				updatePlayerCount();
322 				playerListTable.setRowSorter(sorter);
323 				sorter.setRowFilter(rowFilter);
324 			} else {
325 				//this.selectedIndex = playerListTable.getSelectedRow();
326 			}
327 			return;
328 		}
329 		Player player = playerListPopupMenu.getPlayer();
330 		if (DEBUG)
331 			System.out.println("playerListTable.getSelectedRow() = " + playerListTable.getSelectedRow());
332 		
333 		String playerName = player.getName(); 
334 		if (DEBUG)
335 			System.out.println("Action performed: " + e.getActionCommand() + " on " + playerName);
336 		if (e.getActionCommand().startsWith("inv-")) {
337 			String s = e.getActionCommand().substring(4);
338 			this.commandDispatcher.dispatch(CommandDispatcher.Command.INVITE, playerName, s);
339 		} else if (e.getActionCommand() == "Watch") {
340 			this.commandDispatcher.dispatch(CommandDispatcher.Command.WATCH, playerName);
341 		} else if (e.getActionCommand().startsWith("rep")) {
342 			String s = "tell repbot " + e.getActionCommand().substring(3) + " " + playerName;
343 			this.commandDispatcher.dispatch(CommandDispatcher.Command.SEND_COMMAND, s);
344 			
345 		} else {
346 			System.out.println("Unhandled Action: " + e.getActionCommand() + " on " + playerName);			
347 		}
348 		
349 	}
350 
351 	private	void	onMousePressed(MouseEvent e) {
352 		if (e.getButton() != MouseEvent.BUTTON1)
353 			return;
354 		if (e.getClickCount() != 2)
355 			return;
356 		Player p = (Player)playerListTable.getModel().getValueAt(playerListTable.convertRowIndexToModel(playerListTable.getSelectedRow()), 0);
357 		if (p == null)
358 			return;
359 		String playerName = p.getName();
360 		if (DEBUG)
361 			System.out.println("dblclick performed: on " + playerName);
362 		this.commandDispatcher.dispatch(CommandDispatcher.Command.GET_PLAYER_REPORT, playerName);
363 	}
364 
365 	/**
366 	 * This method initializes jToolBar	
367 	 * 	
368 	 * @return javax.swing.JToolBar	
369 	 */
370 	private JToolBar getJToolBar() {
371 		if (jToolBar == null) {
372 			jToolBar = new JToolBar();
373 			jToolBar.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
374 			jToolBar.setFloatable(false);
375 			jToolBar.add(getReadyToggleButton());
376 			jToolBar.add(getOnlineToggleButton());
377 			jToolBar.add(getPlayingToggleButton());
378 			jToolBar.add(new JToolBar.Separator());
379 			jToolBar.add(getJTextFieldGroup());
380 		}
381 		return jToolBar;
382 	}
383 
384 	/**
385 	 * This method initializes playerListScrollPane	
386 	 * 	
387 	 * @return javax.swing.JScrollPane	
388 	 */
389 	private JScrollPane getPlayerListScrollPane() {
390 		if (playerListScrollPane == null) {
391 			playerListScrollPane = new JScrollPane();
392 			playerListScrollPane.setViewportView(getPlayerListTable());
393 		}
394 		return playerListScrollPane;
395 	}
396 	
397 	private TableRowSorter<PlayerTableModel> sorter;
398 	RowFilter<PlayerTableModel,Integer> rowFilter = new RowFilter<PlayerTableModel,Integer>() {
399 		public boolean include(Entry<? extends PlayerTableModel, ? extends Integer> entry) {
400 			PlayerTableModel playerModel = entry.getModel();
401 			Player player = (Player)playerModel.getValueAt(entry.getIdentifier(), 0);
402 			if (!groupManager.filter(player))
403 				return(false);
404 			if (player.isPlaying())
405 					return(rop[2]);
406 			if (player.isReady())
407 				return(rop[0]);
408 			return(rop[1]);
409 		}
410 	};
411 	private JTextField jTextFieldGroup = null;
412 	private JPanel jPanelDummyAfterGroup = null;
413 	
414 	/** This method initializes playerListTable	
415 	 * @return javax.swing.JTable	
416 	 */
417 	private JTable getPlayerListTable() {
418 		if (playerListTable == null) {
419 			playerTableModel = new PlayerTableModel();
420 			sorter = new TableRowSorter<PlayerTableModel>(playerTableModel);
421 			playerListTable = new JTable(playerTableModel);
422 			playerListTable.addMouseListener(new java.awt.event.MouseAdapter() {   
423 				public void mousePressed(java.awt.event.MouseEvent e) {    
424 					onMousePressed(e);
425 				}
426 			});
427 			playerListTable.setRowSorter(sorter);
428 			sorter.setRowFilter(rowFilter);
429 			playerListTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
430 			for (int i=0; i<playerTableModel.getColumnCount(); i++) {
431 				int w = playerTableModel.getColumnWidth(i);
432 				playerListTable.getColumnModel().getColumn(i).setPreferredWidth(w);
433 			}
434 			playerListTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
435 			playerListTable.setAutoCreateRowSorter(true);
436 
437 			PlayerNameRenderer playerRenderer = new PlayerNameRenderer();
438 			playerListTable.setDefaultRenderer(com.buckosoft.fibs.domain.Player.class, playerRenderer);
439 			playerRenderer.setBackground(playerListTable.getBackground());
440 			playerRenderer.setSelectedBackground(playerListTable.getSelectionBackground());
441 
442 			//Add listener to components that can bring up popup menus.
443 			PopupListener popupListener = new PopupListener();
444 			popupListener.setPlayerListPane(this);
445 			playerListTable.addMouseListener(popupListener);
446 		}
447 		return playerListTable;
448 	}
449 	/**
450 	 * This method initializes readyToggleButton	
451 	 * 	
452 	 * @return javax.swing.JToggleButton	
453 	 */
454 	private JToggleButton getReadyToggleButton() {
455 		if (readyToggleButton == null) {
456 			readyToggleButton = new JToggleButton();
457 			readyToggleButton.setIcon(new ImageIcon(getClass().getResource("/g/pready.gif")));
458 			readyToggleButton.setSelected(true);
459 			readyToggleButton.setMnemonic(KeyEvent.VK_UNDEFINED);
460 			readyToggleButton.addItemListener(new java.awt.event.ItemListener() {
461 				public void itemStateChanged(java.awt.event.ItemEvent e) {
462 					changeROP();
463 				}
464 			});
465 		}
466 		return readyToggleButton;
467 	}
468 
469 	/**
470 	 * This method initializes onlineToggleButton	
471 	 * 	
472 	 * @return javax.swing.JToggleButton	
473 	 */
474 	private JToggleButton getOnlineToggleButton() {
475 		if (onlineToggleButton == null) {
476 			onlineToggleButton = new JToggleButton();
477 			onlineToggleButton.setIcon(new ImageIcon(getClass().getResource("/g/ponline.gif")));
478 			onlineToggleButton.setSelected(true);
479 			onlineToggleButton.addItemListener(new java.awt.event.ItemListener() {
480 				public void itemStateChanged(java.awt.event.ItemEvent e) {
481 					changeROP();
482 				}
483 			});
484 		}
485 		return onlineToggleButton;
486 	}
487 
488 	/**
489 	 * This method initializes playingToggleButton	
490 	 * 	
491 	 * @return javax.swing.JToggleButton	
492 	 */
493 	private JToggleButton getPlayingToggleButton() {
494 		if (playingToggleButton == null) {
495 			playingToggleButton = new JToggleButton();
496 			playingToggleButton.setIcon(new ImageIcon(getClass().getResource("/g/pplaying.gif")));
497 			playingToggleButton.setSelected(true);
498 			playingToggleButton.addItemListener(new java.awt.event.ItemListener() {
499 				public void itemStateChanged(java.awt.event.ItemEvent e) {
500 					changeROP();
501 				}
502 			});
503 		}
504 		return playingToggleButton;
505 	}
506 
507 	private	void changeROP() {
508 		boolean[] rop = new boolean[3];
509 		rop[0] = this.readyToggleButton.getModel().isSelected();
510 		rop[1] = this.onlineToggleButton.getModel().isSelected();
511 		rop[2] = this.playingToggleButton.getModel().isSelected();
512 		this.commandDispatcher.ropChanged(rop);
513 	}
514 
515 	private	PlayerListPopupMenu getPlayerListPopupMenu() { 
516 		if (playerListPopupMenu == null) {
517 			playerListPopupMenu = new PlayerListPopupMenu();
518 			playerListPopupMenu.setMenuHandler(this);
519 		}
520 		return(playerListPopupMenu);
521 	}
522 
523 	private void updatePlayerCount() {
524 		String s = "On: " + this.playerTableModel.getRowCount();
525 		this.jLabelLoggedIn.setText(s);
526 	}
527 
528 	class PopupListener extends MouseAdapter {
529 		PlayerListPane	plp;
530 		
531 		void setPlayerListPane(PlayerListPane plp) {
532 			this.plp = plp;
533 		}
534 		public void mousePressed(MouseEvent e) {
535 			maybeShowPopup(e);
536 		}
537 
538 		public void mouseReleased(MouseEvent e) {
539 			maybeShowPopup(e);
540 		}
541 
542 		private void maybeShowPopup(MouseEvent e) {
543 			if (e.isPopupTrigger()) {
544 				int row = playerListTable.rowAtPoint(new Point(e.getX(), e.getY()));
545 				if (row != -1)
546 					playerListTable.getSelectionModel().setSelectionInterval(row, row);
547 				//if (DEBUG)
548 				//	System.out.println("selected row = " + row);
549 				Player p = (Player)this.plp.playerTableModel.getValueAt(playerListTable.convertRowIndexToModel(playerListTable.getSelectedRow()), 0);
550 				playerListPopupMenu.setPlayer(p);
551 				playerListPopupMenu.rebuildGroups();
552 				playerListPopupMenu.getInvitePopupSubmenu().getJMenuItemResume().setVisible(
553 						p.getSavedMatch() != null);
554 				playerListPopupMenu.getInvitePopupSubmenu().setEnabled(p.isReady());
555 				playerListPopupMenu.show(e.getComponent(),
556 						e.getX(), e.getY());
557 			}
558 		}
559 	}
560 
561 	/**
562 	 * This method initializes jTextFieldGroup	
563 	 * 	
564 	 * @return javax.swing.JTextField	
565 	 */
566 	private JTextField getJTextFieldGroup() {
567 		if (jTextFieldGroup == null) {
568 			jTextFieldGroup = new JTextField();
569 			jTextFieldGroup.setPreferredSize(new Dimension(140, 20));
570 			jTextFieldGroup.setEnabled(true);
571 			jTextFieldGroup.setFont(new Font("Dialog", Font.PLAIN, 14));
572 			jTextFieldGroup.setEditable(false);
573 			jTextFieldGroup.addMouseListener(new java.awt.event.MouseAdapter() {
574 				public void mouseClicked(java.awt.event.MouseEvent e) {
575 					handleGroupPane();
576 				}
577 			});
578 		}
579 		return jTextFieldGroup;
580 	}
581 
582 	/**
583 	 * This method initializes jPanelDummyAfterGroup	
584 	 * 	
585 	 * @return javax.swing.JPanel	
586 	 */
587 	private JPanel getJPanelDummyAfterGroup() {
588 		if (jPanelDummyAfterGroup == null) {
589 			jPanelDummyAfterGroup = new JPanel();
590 			jPanelDummyAfterGroup.setLayout(new GridBagLayout());
591 			jPanelDummyAfterGroup.setPreferredSize(new Dimension(20, 20));
592 		}
593 		return jPanelDummyAfterGroup;
594 	}
595 
596 	private void handleGroupPane() {
597 		if (groupPane == null) {
598 			groupPane = createGroupPane();
599 			GridBagConstraints gridBagConstraints = new GridBagConstraints();
600 			gridBagConstraints.gridheight = 2;
601 			gridBagConstraints.anchor = GridBagConstraints.NORTH;
602 			this.add(groupPane, gridBagConstraints);
603 			groupPane.setVisible(true);
604 			this.revalidate();
605 		} else {
606 			groupPane.setVisible(false);
607 			groupPane.savePaneToList();
608 			groupPane = null;
609 			this.groupManager.save();
610 		}
611 	}
612 	/** GroupManager calls here when one of the groups reports it has changed
613 	 */
614 	public void groupPaneChanged() {
615 		playerListTable.setRowSorter(sorter);
616 		sorter.setRowFilter(rowFilter);
617 		sorter.sort();
618 		getJTextFieldGroup().setText(this.groupManager.getGroupsSelectedString());
619 	}
620 
621 	private GroupSelectPane createGroupPane() {
622 		GroupSelectPane gsp = new GroupSelectPane();
623 		gsp.setGroupManager(this.groupManager);
624 		gsp.setMainDialog(this.mainDialog);
625 		gsp.populatePane();
626 		return(gsp);
627 	}
628 }