1 /** 2 * The chess framework library. 3 * More information is available at http://www.jinchess.com/. 4 * Copyright (C) 2004 Alexander Maryanovsky. 5 * All rights reserved. 6 * 7 * The chess framework library is free software; you can redistribute 8 * it and/or modify it under the terms of the GNU Lesser General Public License 9 * as published by the Free Software Foundation; either version 2 of the 10 * License, or (at your option) any later version. 11 * 12 * The chess framework library is distributed in the hope that it will 13 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public License 18 * along with the chess framework library; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 package free.chess; 23 24 import javax.swing.*; 25 import java.awt.*; 26 import java.util.Hashtable; 27 import java.awt.event.ActionEvent; 28 import java.awt.event.ActionListener; 29 import java.awt.event.KeyEvent; 30 import free.util.AWTUtilities; 31 32 33 /** 34 * A dialog which lets the user choose a Piece from the given set of pieces. 35 */ 36 37 public class PieceChooser extends JComponent implements ActionListener{ 38 39 40 /** 41 * Maps JButtons to Pieces. 42 */ 43 44 private final Hashtable buttonsToPieces = new Hashtable(); 45 46 47 48 /** 49 * Maps pieces to buttons. 50 */ 51 52 private final Hashtable piecesToButtons = new Hashtable(); 53 54 55 56 /** 57 * The selected piece. 58 */ 59 60 private Piece chosenPiece = null; 61 62 63 64 65 /** 66 * Creates a new PieceChooser with the given array of Pieces and the given 67 * PiecePainter. 68 */ 69 PieceChooser(Piece [] pieces, PiecePainter piecePainter)70 public PieceChooser(Piece [] pieces, PiecePainter piecePainter){ 71 int gridSize = (int)Math.round(Math.ceil(Math.sqrt(pieces.length))); 72 setLayout(new GridLayout(gridSize, gridSize, 10, 10)); 73 for (int i=0;i<pieces.length;i++){ 74 Piece piece = pieces[i]; 75 JButton button = new JButton(piece.getTypeName(), new PieceIcon(piece, piecePainter, 32, 32)); 76 button.setVerticalTextPosition(SwingConstants.BOTTOM); 77 button.setHorizontalTextPosition(SwingConstants.CENTER); 78 button.setRolloverEnabled(true); 79 add(button); 80 buttonsToPieces.put(button, piece); 81 piecesToButtons.put(piece, button); 82 button.addActionListener(this); 83 } 84 } 85 86 87 88 89 /** 90 * Returns the selected Piece. 91 */ 92 getSelectedPiece()93 public Piece getSelectedPiece(){ 94 return chosenPiece; 95 } 96 97 98 99 /** 100 * Returns the button corresponding to the specified piece. 101 */ 102 buttonForPiece(Piece piece)103 public JButton buttonForPiece(Piece piece){ 104 return (JButton)piecesToButtons.get(piece); 105 } 106 107 108 109 /** 110 * Displays a modal dialog over the given Component at the specified 111 * coordinates, which lets the user choose from the given set of Pieces which 112 * are painted using the given PiecePainter. Returns the piece chosen by the 113 * user. 114 */ 115 showPieceChooser(Component parentComponent, int x, int y, Piece [] pieces, PiecePainter painter, Piece defaultPiece)116 public static Piece showPieceChooser(Component parentComponent, int x, int y, 117 Piece [] pieces, PiecePainter painter, Piece defaultPiece){ 118 final JDialog dialog = new JDialog(JOptionPane.getFrameForComponent(parentComponent), "Choose a piece", true); 119 120 JComponent content = new JPanel(new BorderLayout()); 121 dialog.setContentPane(content); 122 PieceChooser chooser = new PieceChooser(pieces, painter); 123 content.add(chooser, BorderLayout.CENTER); 124 125 content.registerKeyboardAction(new ActionListener(){ 126 public void actionPerformed(ActionEvent evt){ 127 dialog.dispose(); 128 } 129 }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); 130 131 chooser.addActionListener(new ActionListener(){ 132 public void actionPerformed(ActionEvent evt){ 133 dialog.dispose(); 134 } 135 }); 136 137 JButton defaultButton = chooser.buttonForPiece(defaultPiece); 138 dialog.getRootPane().setDefaultButton(defaultButton); 139 dialog.pack(); 140 Point parentLoc = parentComponent.getLocationOnScreen(); 141 // Try to position the default button under the mouse 142 int locX = parentLoc.x + x - defaultButton.getX() - defaultButton.getWidth()/2; 143 int locY = parentLoc.y + y - defaultButton.getY() - defaultButton.getHeight()/2 - 20; // 20 is what we think is a typical size for the window title. 144 145 dialog.setLocation(locX, locY); 146 AWTUtilities.forceToScreen(dialog); 147 dialog.setVisible(true); 148 149 Piece selectedPiece = chooser.getSelectedPiece(); 150 if (selectedPiece == null) // User closed the dialog... 151 selectedPiece = defaultPiece; 152 153 return selectedPiece; 154 } 155 156 157 158 /** 159 * Handles ActionEvents from the piece buttons. 160 */ 161 actionPerformed(ActionEvent evt)162 public void actionPerformed(ActionEvent evt){ 163 chosenPiece = (Piece)buttonsToPieces.get(evt.getSource()); 164 fireActionPerformed(evt); 165 } 166 167 168 169 170 /** 171 * Adds an ActionListener to this PieceChooser. An ActionEvent is fired when 172 * a piece is chosen. 173 */ 174 addActionListener(ActionListener listener)175 public void addActionListener(ActionListener listener){ 176 listenerList.add(ActionListener.class, listener); 177 } 178 179 180 181 /** 182 * Removes an ActionListener from this PieceChooser. 183 */ 184 removeActionListener(ActionListener listener)185 public void removeActionListener(ActionListener listener){ 186 listenerList.remove(ActionListener.class, listener); 187 } 188 189 190 191 192 /** 193 * Fires an ActionEvent. 194 */ 195 fireActionPerformed(ActionEvent evt)196 protected void fireActionPerformed(ActionEvent evt){ 197 Object [] listeners = listenerList.getListenerList(); 198 ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, evt.getActionCommand(), evt.getModifiers()); 199 200 for (int i=0; i<listeners.length; i+=2) { 201 if (listeners[i]==ActionListener.class) { 202 ((ActionListener)listeners[i+1]).actionPerformed(e); 203 } 204 } 205 } 206 207 } 208