/**
* Copyright (C) 2002-2012 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol 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.
*
* FreeCol 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 FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.option;
import java.awt.Color;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import net.miginfocom.swing.MigLayout;
import net.sf.freecol.client.gui.GUI;
import net.sf.freecol.client.gui.i18n.Messages;
import net.sf.freecol.common.model.FreeColObject;
import net.sf.freecol.common.option.Option;
import net.sf.freecol.common.option.OptionGroup;
/**
* This panel displays an OptionGroup using a JTree.
*/
public final class OptionGroupUI extends JPanel
implements OptionUpdater, TreeSelectionListener {
private static final Logger logger = Logger.getLogger(OptionGroupUI.class.getName());
private final List<OptionUpdater> optionUpdaters = new ArrayList<OptionUpdater>();
private final HashMap<String, OptionUI> optionUIs = new HashMap<String, OptionUI>();
private JPanel detailPanel;
private JTree tree;
private GUI gui;
private OptionGroup group;
private boolean editable;
/**
* The constructor that will add the items to this panel.
*
* @param gui
* @param group
* @param editable
*/
public OptionGroupUI(GUI gui, OptionGroup group, boolean editable) {
this.gui = gui;
this.group = group;
this.editable = editable;
setLayout(new MigLayout("fill", "[200:]unrelated[550:, grow, fill]", "[top]"));
DefaultMutableTreeNode root = new DefaultMutableTreeNode(group);
buildTree(group, root);
DefaultTreeModel treeModel = new DefaultTreeModel(root);
tree = new JTree(treeModel) {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, super.getPreferredSize().height);
}
@Override
public String convertValueToText(Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
Option option = (Option) node.getUserObject();
return Messages.message(option.getId() + ".name");
}
};
tree.setOpaque(false);
tree.addTreeSelectionListener(this);
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) tree.getCellRenderer();
renderer.setBackgroundNonSelectionColor(new Color(0,0,0,1));
add(tree);
detailPanel = new JPanel(new MigLayout("wrap 2", "[fill]related[fill]"));
detailPanel.setOpaque(false);
add(detailPanel, "grow");
}
public JTree getTree() {
return tree;
}
/**
* Builds the JTree which represents the navigation menu and then returns it
*
*/
private void buildTree(OptionGroup group, DefaultMutableTreeNode parent) {
for (Option option : group.getOptions()) {
if (option instanceof OptionGroup) {
DefaultMutableTreeNode branch = new DefaultMutableTreeNode(option);
parent.add(branch);
buildTree((OptionGroup) option, branch);
}
}
}
/**
* This function analyses a tree selection event and calls the right methods to take care
* of building the requested unit's details.
*
* @param event The incoming TreeSelectionEvent.
*/
public void valueChanged(TreeSelectionEvent event) {
detailPanel.removeAll();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
if (node != null) {
if (node.isLeaf()) {
OptionGroup group = (OptionGroup) node.getUserObject();
for (Option option : group.getOptions()) {
addOptionUI(option, editable && group.isEditable());
}
} else {
tree.expandPath(event.getPath());
}
}
detailPanel.revalidate();
detailPanel.repaint();
}
/**
* Updates the value of the {@link net.sf.freecol.common.option.Option} this object keeps.
*/
public void updateOption() {
for (OptionUpdater optionUpdater : optionUpdaters) {
optionUpdater.updateOption();
}
}
public OptionUI getOptionUI(String key) {
return optionUIs.get(key);
}
private void addOptionUI(Option option, boolean editable) {
OptionUI ui = OptionUI.getOptionUI(gui, option, editable);
if (ui == null) {
logger.warning("Unknown option type: " + option.toString());
} else if (ui instanceof FreeColActionUI) {
((FreeColActionUI) ui).setOptionGroupUI(this);
}
JLabel label = ui.getLabel();
if (label == null) {
detailPanel.add(ui.getComponent(), "newline, span");
} else {
detailPanel.add(label);
detailPanel.add(ui.getComponent());
}
if (group.isEditable()) {
optionUpdaters.add((OptionUpdater) ui);
}
if (!option.getId().equals(FreeColObject.NO_ID)) {
optionUIs.put(option.getId(), ui);
}
}
/**
* Removes the given <code>KeyStroke</code> from all of this
* <code>OptionGroupUI</code>'s children.
*
* @param keyStroke The <code>KeyStroke</code> to be removed.
*/
public void removeKeyStroke(KeyStroke keyStroke) {
for (OptionUpdater optionUpdater : optionUpdaters) {
if (optionUpdater instanceof FreeColActionUI) {
((FreeColActionUI) optionUpdater).removeKeyStroke(keyStroke);
}
}
}
/**
* Reset with the value from the option.
*/
public void reset() {
for (OptionUpdater optionUpdater : optionUpdaters) {
optionUpdater.reset();
}
}
@Override
public String getUIClassID() {
return "ReportPanelUI";
}
}