/**
* Created on 22.02.2004
*FreeMind - A Program for creating and viewing Mindmaps
*Copyright (C) 2000-2001 Joerg Mueller <joergmueller@bigfoot.com>
*See COPYING for Details
*
*This program is free software; you can redistribute it and/or
*modify it under the terms of the GNU General Public License
*as published by the Free Software Foundation; either version 2
*of the License, or (at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program; if not, write to the Free Software
*Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @author <a href="mailto:labe@users.sourceforge.net">Lars Berning</a>
*/
package freemind.modes.common.dialogs;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.border.BevelBorder;
import freemind.main.FreeMindMain;
import freemind.modes.IconInformation;
public class IconSelectionPopupDialog extends JDialog implements KeyListener,
MouseListener {
private Vector icons;
private int result;
private JPanel iconPanel = new JPanel();
private JLabel[] iconLabels;
private JLabel descriptionLabel;
private int numOfIcons;
private int xDimension;
private int yDimension;
private Position selected = new Position(0, 0);
private static Position lastPosition = new Position(0, 0);
private FreeMindMain freeMindMain;
private int mModifiers;
public IconSelectionPopupDialog(JFrame caller, Vector icons,
FreeMindMain freeMindMain) {
super(caller, freeMindMain.getResourceString("select_icon"));
getContentPane().setLayout(new BorderLayout());
this.freeMindMain = freeMindMain;
this.icons = icons;
setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
close();
}
});
// we will build a button-matrix which is closest to quadratical
numOfIcons = icons.size();
xDimension = new Double(Math.ceil(Math.sqrt(numOfIcons))).intValue();
if (numOfIcons <= xDimension * (xDimension - 1))
yDimension = xDimension - 1;
else
yDimension = xDimension;
GridLayout gridlayout = new GridLayout(0, xDimension);
gridlayout.setHgap(3);
gridlayout.setVgap(3);
iconPanel.setLayout(gridlayout);
iconLabels = new JLabel[numOfIcons];
for (int i = 0; i < numOfIcons; ++i) {
final IconInformation icon = (IconInformation) icons.get(i);
iconPanel.add(iconLabels[i] = new JLabel(icon.getIcon()));
iconLabels[i].setBorder(BorderFactory
.createBevelBorder(BevelBorder.RAISED));
iconLabels[i].addMouseListener(this);
}
int perIconSize = 27;
iconPanel.setPreferredSize(new Dimension(xDimension * perIconSize,
yDimension * perIconSize));
iconPanel.setMinimumSize(new Dimension(xDimension * perIconSize,
yDimension * perIconSize));
iconPanel.setMaximumSize(new Dimension(xDimension * perIconSize,
yDimension * perIconSize));
iconPanel.setSize(new Dimension(xDimension * perIconSize, yDimension
* perIconSize));
getContentPane().add(iconPanel, BorderLayout.CENTER);
descriptionLabel = new JLabel(" ");
// descriptionLabel.setEnabled(false);
getContentPane().add(descriptionLabel, BorderLayout.SOUTH);
setSelectedPosition(lastPosition);
select(getSelectedPosition());
addKeyListener(this);
pack();
}
private boolean canSelect(Position position) {
return ((position.getX() >= 0) && (position.getX() < xDimension)
&& (position.getY() >= 0) && (position.getY() < yDimension) && (calculateIndex(position) < numOfIcons));
}
private int calculateIndex(Position position) {
return position.getY() * xDimension + position.getX();
}
private Position getPosition(JLabel caller) {
int index = 0;
for (index = 0; index < iconLabels.length; index++) {
if (caller == iconLabels[index])
break;
}
return getPositionFromIndex(index);
}
private Position getPositionFromIndex(int index) {
return new Position(index % xDimension, index / xDimension);
}
private void setSelectedPosition(Position position) {
selected = position;
lastPosition = position;
}
private Position getSelectedPosition() {
return selected;
}
private void select(Position position) {
unhighlight(getSelectedPosition());
setSelectedPosition(position);
highlight(position);
final int index = calculateIndex(position);
final IconInformation iconInformation = (IconInformation) icons
.get(index);
final String keyStroke = freeMindMain
.getAdjustableProperty(iconInformation
.getKeystrokeResourceName());
if (keyStroke != null) {
descriptionLabel.setText(iconInformation.getDescription() + ", "
+ keyStroke);
} else {
descriptionLabel.setText(iconInformation.getDescription());
}
}
private void unhighlight(Position position) {
iconLabels[calculateIndex(position)].setBorder(BorderFactory
.createBevelBorder(BevelBorder.RAISED));
}
private void highlight(Position position) {
iconLabels[calculateIndex(position)].setBorder(BorderFactory
.createBevelBorder(BevelBorder.LOWERED));
}
private void cursorLeft() {
Position newPosition = new Position(getSelectedPosition().getX() - 1,
getSelectedPosition().getY());
if (canSelect(newPosition))
select(newPosition);
}
private void cursorRight() {
Position newPosition = new Position(getSelectedPosition().getX() + 1,
getSelectedPosition().getY());
if (canSelect(newPosition))
select(newPosition);
}
private void cursorUp() {
Position newPosition = new Position(getSelectedPosition().getX(),
getSelectedPosition().getY() - 1);
if (canSelect(newPosition))
select(newPosition);
}
private void cursorDown() {
Position newPosition = new Position(getSelectedPosition().getX(),
getSelectedPosition().getY() + 1);
if (canSelect(newPosition))
select(newPosition);
}
private void addIcon(int pModifiers) {
result = calculateIndex(getSelectedPosition());
mModifiers = pModifiers;
this.dispose();
}
public int getResult() {
return result;
}
/**
* Transfer shift masks from InputEvent to ActionEvent. But, why don't they
* use the same constants???? Java miracle.
*/
public int getModifiers() {
int m = mModifiers;
if ((mModifiers & (ActionEvent.SHIFT_MASK | InputEvent.SHIFT_DOWN_MASK)) != 0)
m |= ActionEvent.SHIFT_MASK;
if ((mModifiers & (ActionEvent.CTRL_MASK | InputEvent.CTRL_DOWN_MASK)) != 0)
m |= ActionEvent.CTRL_MASK;
if ((mModifiers & (ActionEvent.ALT_MASK | InputEvent.ALT_DOWN_MASK)) != 0)
m |= ActionEvent.ALT_MASK;
return m;
}
/*
* (non-Javadoc)
*
* @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
*/
public void keyPressed(KeyEvent keyEvent) {
switch (keyEvent.getKeyCode()) {
case KeyEvent.VK_RIGHT:
case KeyEvent.VK_KP_RIGHT:
cursorRight();
return;
case KeyEvent.VK_LEFT:
case KeyEvent.VK_KP_LEFT:
cursorLeft();
return;
case KeyEvent.VK_DOWN:
case KeyEvent.VK_KP_DOWN:
cursorDown();
return;
case KeyEvent.VK_UP:
case KeyEvent.VK_KP_UP:
cursorUp();
return;
case KeyEvent.VK_ESCAPE:
keyEvent.consume();
close();
return;
case KeyEvent.VK_ENTER:
case KeyEvent.VK_SPACE:
keyEvent.consume();
addIcon(keyEvent.getModifiers());
return;
}
int index = findIndexByKeyEvent(keyEvent);
if (index != -1) {
result = index;
lastPosition = getPositionFromIndex(index);
mModifiers = keyEvent.getModifiers();
keyEvent.consume();
this.dispose();
}
}
private KeyStroke getKeyStrokeForEvent(KeyEvent keyEvent) {
if (keyEvent.getKeyChar() != 0) {
return KeyStroke.getKeyStroke(keyEvent.getKeyChar());
}
return KeyStroke.getKeyStroke(keyEvent.getKeyCode(), 0);
}
private int findIndexByKeyEvent(KeyEvent keyEvent) {
for (int i = 0; i < icons.size(); i++) {
IconInformation info = (IconInformation) icons.get(i);
final KeyStroke iconKeyStroke = info.getKeyStroke();
if (iconKeyStroke != null
&& (keyEvent.getKeyCode() == iconKeyStroke.getKeyCode()
&& keyEvent.getKeyCode() != 0
&& (iconKeyStroke.getModifiers() & KeyEvent.SHIFT_MASK) == (keyEvent
.getModifiers() & KeyEvent.SHIFT_MASK) || keyEvent
.getKeyChar() == iconKeyStroke.getKeyChar())
&& keyEvent.getKeyChar() != 0
&& keyEvent.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
return i;
}
}
return -1;
}
private void close() {
result = -1;
mModifiers = 0;
this.dispose();
}
/*
* (non-Javadoc)
*
* @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
*/
public void keyReleased(KeyEvent arg0) {
}
/*
* (non-Javadoc)
*
* @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
*/
public void keyTyped(KeyEvent arg0) {
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
*/
public void mouseClicked(MouseEvent mouseEvent) {
addIcon(mouseEvent.getModifiers());
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
*/
public void mouseEntered(MouseEvent arg0) {
select(getPosition((JLabel) arg0.getSource()));
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
*/
public void mouseExited(MouseEvent arg0) {
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
*/
public void mousePressed(MouseEvent arg0) {
}
/*
* (non-Javadoc)
*
* @see
* java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
*/
public void mouseReleased(MouseEvent arg0) {
}
static class Position {
private int x, y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
/**
* @return Returns the x.
*/
public int getX() {
return x;
}
/**
* @return Returns the y.
*/
public int getY() {
return y;
}
public String toString() {
return ("(" + getX() + "," + getY() + ")");
}
}
}