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